NettyはHTTP demoを実現

15727 ワード

1.プロセス分析の実現
  • 履歴書接続読み出しメッセージストリーム
  • 復号Request
  • 業務処理
  • 符号化Response
  • は、メッセージクローズ接続
  • を返す.
    2.nettyにおけるHttpRequestの表示構造
    Netty 实现HTTP demo_第1张图片
    3.nettyにおけるHttpResponseの構造:
    Netty 实现HTTP demo_第2张图片
    4.コード実装
    public class HttpServer {
    
        private final int port;
    
        public HttpServer(int port) {
            this.port = port;
        }
    
        public void run() {
            EventLoopGroup bossGroup = new NioEventLoopGroup(1);
            EventLoopGroup workerGroup = new NioEventLoopGroup();
    
            try {
                ServerBootstrap bootstrap = new ServerBootstrap();
                bootstrap.group(bossGroup, workerGroup).option(ChannelOption.SO_BACKLOG, 1024)
                        .channel(NioServerSocketChannel.class).childOption(ChannelOption.SO_KEEPALIVE, true)
                        .childOption(ChannelOption.TCP_NODELAY, true).childHandler(new ChannelInitializer() {
                            protected void initChannel(SocketChannel ch) throws Exception {
                                ch.pipeline().addLast("codec", new HttpServerCodec()) //     HttpRequestDecoder
                                        .addLast("aggregator", new HttpObjectAggregator(1024 * 1024)) //    
                                        .addLast("handler", new HttpServerhandler()); //   handler
                            };
                        });
                ChannelFuture future = bootstrap.bind(port).sync();
    
                System.out.println("Netty-http server listening on port " + port);
                future.channel().closeFuture().sync();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }
    
        public static void main(String[] args) {
            new HttpServer(8080).run();
        }
    }
    
    public class HttpServerhandler extends ChannelHandlerAdapter {
        private HttpHeaders headers;
        private HttpRequest request;
        private FullHttpRequest fullRequest;
        private FullHttpResponse response;
    
        private HttpPostRequestDecoder decoder;
    
        private static final HttpDataFactory factory = new DefaultHttpDataFactory(DefaultHttpDataFactory.MAXSIZE);
    
        private static final String FAVICON_ICO = "/favicon.ico";
        private static final String SUCCESS = "success";
        private static final String ERROR = "error";
        private static final String CONNECTION_KEEP_ALIVE = "keep-alive";
        private static final String CONNECTION_CLOSE = "close";
        private static final Charset cs = Charset.forName("utf-8");
    
        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            ctx.flush();
        }
    
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            if (msg instanceof HttpRequest) {
                try {
                    request = (HttpRequest) msg;
                    headers = request.headers();
    
                    String uri = request.uri();
                    System.out.println("http uri: " + uri);
                    //      "/favicon.ico"   
                    if (uri.equals(FAVICON_ICO)) {
                        return;
                    }
    
                    HttpMethod method = request.method();
                    if (method.equals(HttpMethod.GET)) {
                        QueryStringDecoder queryDecoder = new QueryStringDecoder(uri, cs);
                        Map> uriAttributes = queryDecoder.parameters();
                        //          (              )
                        for (Map.Entry> attr : uriAttributes.entrySet()) {
                            for (String attrVal : attr.getValue()) {
                                System.out.println(attr.getKey() + "=" + attrVal);
                            }
                        }
                    } else if (method.equals(HttpMethod.POST)) {
    
                        // POST  ,              ,      msg   FullHttpRequest
                        fullRequest = (FullHttpRequest) msg;
    
                        //       Content_Type    body   
                        dealWithContentType();
                    } else {
                        //           ,         
                    }
    
                    writeResponse(ctx.channel(), HttpResponseStatus.OK, SUCCESS, false);
    
                } catch (Exception e) {
                    writeResponse(ctx.channel(), HttpResponseStatus.INTERNAL_SERVER_ERROR, ERROR, true);
    
                } finally {
                    ReferenceCountUtil.release(msg);
                }
    
            } else {
                // discard request...
                ReferenceCountUtil.release(msg);
            }
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            cause.printStackTrace();
            ctx.close();
        }
    
        /**
         *          Content-Type   POST   (     )
         * 
         * @param headers
         * @param content
         * @throws Exception
         */
        private void dealWithContentType() throws Exception {
            String contentType = getContentType();
            if (contentType.equals("application/json")) { //     HttpJsonDecoder
                String jsonStr = fullRequest.content().toString(cs);
                JSONObject obj = JSON.parseObject(jsonStr);
                for (Entry item : obj.entrySet()) {
                    System.out.println(item.getKey() + "=" + item.getValue().toString());
                }
    
            } else if (contentType.equals("application/x-www-form-urlencoded")) {
                //    :   QueryStringDecoder
                // String jsonStr =
                // fullRequest.content().toString(Charsets.toCharset(CharEncoding.UTF_8));
                // QueryStringDecoder queryDecoder = new QueryStringDecoder(jsonStr,
                // false);
                // Map> uriAttributes =
                // queryDecoder.parameters();
                // for (Map.Entry> attr :
                // uriAttributes.entrySet()) {
                // for (String attrVal : attr.getValue()) {
                // System.out.println(attr.getKey() + "=" + attrVal);
                // }
                // }
                //    :   HttpPostRequestDecoder
                initPostRequestDecoder();
                List datas = decoder.getBodyHttpDatas();
                for (InterfaceHttpData data : datas) {
                    if (data.getHttpDataType() == HttpDataType.Attribute) {
                        Attribute attribute = (Attribute) data;
                        System.out.println(attribute.getName() + "=" + attribute.getValue());
                    }
                }
    
            } else if (contentType.equals("multipart/form-data")) { //       
                readHttpDataAllReceive();
    
            } else {
                // do nothing...
            }
        }
    
        private void readHttpDataAllReceive() throws Exception {
            initPostRequestDecoder();
            try {
                List datas = decoder.getBodyHttpDatas();
                for (InterfaceHttpData data : datas) {
                    writeHttpData(data);
                }
            } catch (Exception e) {
                //                  ,      
                throw new Exception(e);
            }
        }
    
        private void writeHttpData(InterfaceHttpData data) throws Exception {
            //         (HttpChunk),       
            if (data.getHttpDataType() == HttpDataType.FileUpload) {
                FileUpload fileUpload = (FileUpload) data;
                String fileName = fileUpload.getFilename();
                if (fileUpload.isCompleted()) {
                    //      
                    StringBuffer fileNameBuf = new StringBuffer();
                    fileNameBuf.append(DiskFileUpload.baseDirectory).append(fileName);
                    fileUpload.renameTo(new File(fileNameBuf.toString()));
                }
            }
        }
    
        private void writeResponse(Channel channel, HttpResponseStatus status, String msg, boolean forceClose) {
            ByteBuf byteBuf = Unpooled.wrappedBuffer(msg.getBytes());
            response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, byteBuf);
            boolean close = isClose();
            if (!close && !forceClose) {
                response.headers().add(org.apache.http.HttpHeaders.CONTENT_LENGTH, String.valueOf(byteBuf.readableBytes()));
            }
            ChannelFuture future = channel.write(response);
            if (close || forceClose) {
                future.addListener(ChannelFutureListener.CLOSE);
            }
        }
    
        private String getContentType() {
            String typeStr = headers.get("Content-Type").toString();
            String[] list = typeStr.split(";");
            return list[0];
        }
    
        private void initPostRequestDecoder() {
            if (decoder != null) {
                decoder.cleanFiles();
                decoder = null;
            }
    
            decoder = new HttpPostRequestDecoder(factory, request, cs);
        }
    
        private boolean isClose() {
            if (request.headers().contains(org.apache.http.HttpHeaders.CONNECTION, CONNECTION_CLOSE, true) || (request
                    .protocolVersion().equals(HttpVersion.HTTP_1_0)
                    && !request.headers().contains(org.apache.http.HttpHeaders.CONNECTION, CONNECTION_KEEP_ALIVE, true)))
                return true;
            return false;
        }
    
    }