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
@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內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 關於Netty–Http請求處理方式
- 帶你快速上手Servlet
- Java中使用Filter過濾器的方法
- SpringBoot過濾器實現項目內接口過濾詳解
- Tomcat架構設計及Servlet作用規范講解