netty 实现tomcat
o_瓜田李下_o 人气:0netty 实现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请求方法,不支持其它方法
加载全部内容