netty 实现tomcat的示例代码
作者:o_瓜田李下_o
这篇文章主要介绍了netty 实现tomcat,主要包括自定义基础类及netty 服务端的示例代码详解,通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
netty 实现tomcat
自定义基础类
TomcatServlet
public abstract class TomcatServlet { public void service(ServletRequest request, ServletResponse response){ if ("GET".equalsIgnoreCase(request.getMethod())){ doGet(request, response); }else if ("POST".equalsIgnoreCase(request.getMethod())){ doPost(request, response); }else { doResponse(response, "暂不支持其它请求方法"); } } public abstract void doGet(ServletRequest request, ServletResponse response); public abstract void doPost(ServletRequest request, ServletResponse response); public void doResponse(ServletResponse response, String message){ response.write(message); } }
ServletRequest
@Data public class ServletRequest { private ChannelHandlerContext context; private HttpRequest httpRequest; public ServletRequest(){ } public ServletRequest(ChannelHandlerContext context, HttpRequest httpRequest){ this.context = context; this.httpRequest = httpRequest; } public String getMethod(){ return httpRequest.method().name(); } public HttpHeaders getHeaders(){ return httpRequest.headers(); } public Map<String, List<String>> getParameters(){ QueryStringDecoder decoder = new QueryStringDecoder(httpRequest.uri()); return decoder.parameters(); } public Map<String,String> getPostFormParameters(){ Map<String,String> params = new HashMap<>(); HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(httpRequest); decoder.getBodyHttpDatas().forEach(item -> { if (item.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute){ Attribute attribute = (Attribute) item; try { String key = attribute.getName(); String value = attribute.getValue(); params.put(key, value); }catch (Exception e){ e.printStackTrace(); } } }); return params; } public Map<String, Object> getPostBody(){ ByteBuf content = ((FullHttpRequest)httpRequest).content(); byte[] bytes = new byte[content.readableBytes()]; content.readBytes(bytes); return JSON.parseObject(new String(bytes)).getInnerMap(); } }
ServletResponse
@Data public class ServletResponse { private ChannelHandlerContext context; private HttpRequest httpRequest; public ServletResponse(){ } public ServletResponse(ChannelHandlerContext context, HttpRequest httpRequest){ this.context = context; this.httpRequest = httpRequest; } public void write(String message){ FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); response.headers().set("Content-Type","application/json;charset=utf-8"); response.content().writeCharSequence(message, StandardCharsets.UTF_8); context.channel().writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); } }
CustomServlet
ublic class CustomServlet extends TomcatServlet{ @Override public void doGet(ServletRequest request, ServletResponse response) { System.out.println("处理GET请求"); System.out.println("请求参数为:"); request.getParameters().forEach((key,value) -> System.out.println(key + " ==> "+value)); doResponse(response, "GET success"); } @Override public void doPost(ServletRequest request, ServletResponse response) { if (request.getHeaders().get("Content-Type").contains("x-www-form-urlencoded")){ System.out.println("处理POST Form请求"); System.out.println("请求参数为:"); request.getPostFormParameters().forEach((key,value) -> System.out.println(key + " ==> " + value)); doResponse(response, "POST Form success"); }else if (request.getHeaders().get("Content-Type").contains("application/json")){ System.out.println("处理POST json请求"); System.out.println("请求参数为:"); request.getPostBody().forEach((key,value) -> System.out.println(key + " ==> " + value)); doResponse(response, "POST json success"); }else { doResponse(response, "error:暂不支持其它post请求方式"); } } }
ServletMapping:url与对应的TomcatServlet映射
public class ServletMapping { private static final Map<String,TomcatServlet> urlServletMapping = new HashMap<>(); public static Map<String, TomcatServlet> getUrlServletMapping(){ return urlServletMapping; } }
web.properties:使用properties存储url与对应的TomcatServet
servlet.url=/hello servlet.className=com.example.demo.tomcat.servlet.CustomServlet
netty 服务端
CustomServerHandler
public class CustomServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> { @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, FullHttpRequest request) throws Exception { String uri = request.uri(); String path = uri; if (uri.contains("?")){ path = uri.substring(0,uri.indexOf("?")); } if (ServletMapping.getUrlServletMapping().containsKey(path)){ ServletRequest servletRequest = new ServletRequest(channelHandlerContext, request); ServletResponse servletResponse = new ServletResponse(channelHandlerContext, request); ServletMapping.getUrlServletMapping().get(path).service(servletRequest, servletResponse); }else { FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); response.content().writeCharSequence("404 NOT FOUND:"+path+"不存在", StandardCharsets.UTF_8); channelHandlerContext.channel().writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); } } }
NettyServer
public class NettyServer { private static final Properties webProperties = new Properties(); public static void init(){ try { InputStream inputStream = new FileInputStream("./web.properties"); webProperties.load(inputStream); for (Object item : webProperties.keySet()){ String key = (String)item; if (key.endsWith(".url")){ String servletKey = key.replaceAll("\\.url","\\.className"); String servletName = webProperties.getProperty(servletKey); TomcatServlet servlet = (TomcatServlet) Class.forName(servletName).newInstance(); ServletMapping.getUrlServletMapping().put(webProperties.getProperty(key),servlet); } } }catch (Exception e){ e.printStackTrace(); } } public static void startServer(int port){ init(); EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline channelPipeline = socketChannel.pipeline(); channelPipeline.addLast(new HttpRequestDecoder()); channelPipeline.addLast(new HttpResponseEncoder()); channelPipeline.addLast(new HttpObjectAggregator(65535)); channelPipeline.addLast(new CustomServerHandler()); } }); ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); channelFuture.channel().closeFuture().sync(); }catch (Exception e){ e.printStackTrace(); }finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) { startServer(8000); } }
使用测试
get请求:localhost:8000/hello?name=瓜田李下&age=20
处理GET请求
请求参数为:
name ==> [瓜田李下]
age ==> [20]
get请求:localhost:8000/hello2?name=瓜田李下&age=20
/hello2路径没有对应的TomcatServlet处理
Post form请求:x-www-form-urlencoded
处理POST Form请求
请求参数为:
name ==> 瓜田李下
age ==> 20
Post json请求
处理POST json请求
请求参数为:
name ==> 瓜田李下
age ==> 20
Post form-data请求
目前只支持x-www-form-urlencoded、post json请求,不支持其它请求方式
Put:localhost:8000/hello?name=瓜田李下&age=20
目前只支持GET、POST请求方法,不支持其它方法
到此这篇关于netty 实现tomcat的文章就介绍到这了,更多相关netty 实现tomcat内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!