Article directory
Summary
At present, the mainstream Java web server is implemented by springboot+Tomcat, and the bottom layer is developed based on servlet. Servlet is not asynchronous, so its performance is not very rational and cannot meet the requirements of the current fast server.
At present, spring 5 has realized asynchronous programming (responsive programming) based on reactor, and spring boot 2. X has also supported webplus, so the performance will be improved a lot. The underlying implementation is netty.
To learn more about reactive programming, go to my blog: Java 9 responsive programming support , which includes what is reactive programming, reactor's basic explanation and using reactive programming in spring boot.
Therefore, netty can not only be used as component communication, but also as HTTP server. Next, let's see how to use netty to implement HTTP server.
In this paper, we just use netty to build HTTP server. The function is not perfect enough and it can not be used for production service.
HTTP server code implementation
Write an HTTP server service class.
public class MyHttpServer { int port ; public MyHttpServer(int port){ this.port = port; } public void start() throws Exception{ ServerBootstrap bootstrap = new ServerBootstrap(); EventLoopGroup boss = new NioEventLoopGroup(); EventLoopGroup work = new NioEventLoopGroup(); bootstrap.group(boss,work) .handler(new LoggingHandler(LogLevel.DEBUG)) .channel(NioServerSocketChannel.class) .childHandler(new HttpServerInitializer()); ChannelFuture f = bootstrap.bind(new InetSocketAddress(port)).sync(); System.out.println("http server started . port : " + port); f.channel().closeFuture().sync(); } public static void main(String[] args) throws Exception{ MyHttpServer server = new MyHttpServer(8080);// 8080 is the start port server.start(); } } class HttpServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel channel) throws Exception { ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(new HttpServerCodec());// http codec pipeline.addLast("httpAggregator",new HttpObjectAggregator(512*1024)); // http message aggregator 512 * 1024 is the maximum content length received pipeline.addLast(new HttpRequestHandler());// Request processor } }
The above code mainly looks at the HttpServerInitializer class.
In my channel pipeline, HttpServerCodec, HttpObjectAggregator and HttpRequestHandler are added successively.
- HttpServerCodec is the codec for HTTP messages. HttpServerCodec is a composite class of HttpRequestDecoder and HttpResponseEncoder, which is used to simplify HTTP programming.
- HttpRequestDecoder decodes ByteBuf to HttpRequest and HttpContent.
- HttpResponseEncoder is to encode HttpResponse or HttpContent to ByteBuf.
- HttpObjectAggregator is used to aggregate HTTP messages, transforming multiple messages into a single FullHttpRequest and FullHttpResponse. Because the HttpServerCodec decoder produces multiple objects in each HTTP message: HttpRequest, HttpResponse, HttpContent, LastHttpContent.
- HttpRequestHandler is our business logic processing class.
Request processing class HttpRequestHandler:
class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> { @Override public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) { // Get the requested uri String uri = req.uri(); Map<String,String> resMap = new HashMap<>(); resMap.put("method",req.method().name()); resMap.put("uri",uri); String msg = "<html><head><title>test</title></head><body>Your request uri For:" + uri+"</body></html>"; // Create http response FullHttpResponse response = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8)); // Set header information response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8"); //response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8"); // Write HTML to client ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); } }
Simply, it reads the request URL and replies to the client with a string.
Verification
Startup service
The browser accesses any string of localhost:8080 /. For example: http://localhost:8080/index1/q
In the browser page, return to:
Your request uri is: / index1/q