Netty學習——用Netty實現一個簡單的Http伺服器
阿新 • • 發佈:2019-02-16
跟前面的伺服器-客戶端通訊的例子大同小異,也是新增兩個EventLoopGroup,然後建立一個ServerBootstrap,再把兩個EventLoopGroup註冊到ServerBootstrap中,新增相應的引數,實現SocketChannel初始化器,然後新增相應的處理器,處理器的功能就是相應註釋的說明。在繼承自SimpleChannelInboundHandler的類中實現自己的處理請求的業務功能,如果是get請求,那麼引數就是請求的URI中,解析出?後面的就是請求引數,如果是post請求,那麼請求引數就是請求體中,通過獲取resquest的content,得到一個緩衝物件,然後把這個緩衝物件中的資料提取出來就解析出了post請求的請求引數。再然後構造一個DefaultFullHttpResponse物件,向這個response的響應體中寫入頁面的資料,最後呼叫ctx的writeAndFlush把response物件寫回給請求客戶端,並新增CLOSE監聽,如果不新增的話,Netty就不能知道請求的業務邏輯是否已經結束,也就不知道是否應該結束http的一次請求會話。程式的執行結果就是無論是get請求還是post請求,返回都面都可以返回請求的方法型別還有請求的引數。package study.netty; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpRequestEncoder; import io.netty.handler.codec.http.HttpResponseEncoder; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.stream.ChunkedWriteHandler; import io.netty.util.CharsetUtil; public class NettyHttpServer { public static void main(String[] args) { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .option(ChannelOption.SO_BACKLOG, 1024) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast("http-decoder",new HttpRequestDecoder()); ch.pipeline().addLast("http-aggregator",new HttpObjectAggregator(65535));//將多個訊息轉化成一個 ch.pipeline().addLast("http-encoder",new HttpResponseEncoder()); ch.pipeline().addLast("http-chunked",new ChunkedWriteHandler());//解決大碼流的問題 ch.pipeline().addLast("http-server",new HttpHandler()); } }); ChannelFuture future = bootstrap.bind("localhost",8888); try { future.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); }finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } private static class HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest>{ @Override protected void messageReceived(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception { try { ByteBuf content = msg.content(); byte[] bts = new byte[content.readableBytes()]; content.readBytes(bts); String result = null; if(msg.getMethod() == HttpMethod.GET) { String url = msg.getUri().toString(); result = "get method and paramters is "+ url.substring(url.indexOf("?")+1); }else if(msg.getMethod() == HttpMethod.POST) { result = "post method and paramters is "+ new String(bts); } FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); response.headers().set("content-Type","text/html;charset=UTF-8"); StringBuilder sb = new StringBuilder(); sb.append("<html>") .append("<head>") .append("<title>netty http server</title>") .append("</head>") .append("<body>") .append(result) .append("</body>") .append("</html>\r\n"); ByteBuf responseBuf = Unpooled.copiedBuffer(sb,CharsetUtil.UTF_8); response.content().writeBytes(responseBuf); responseBuf.release(); ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); }catch (Exception e) { e.printStackTrace(); } } } }