这篇文章主要介绍“netty如何实现tomcat”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“netty如何实现tomcat”文章能帮助大家解决问题。
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
@Datapublic 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
@Datapublic 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=/helloservlet.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”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网行业资讯频道,小编每天都会为大家更新不同的知识点。