Skip to content

Netty 实现 Http 案例

HttpServer

java
public class HttpServer {

    public static void main(String[] args) throws Exception{

        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();

            bootstrap.group(bossGroup,workerGroup)
                    .channel(NioServerSocketChannel.class)
                    //这里单独抽成了独立类 ServerInitializer
                    .childHandler(new ServerInitializer());//作用于 workerGroup
                    // 作用于 bossGroup
                    //.handler(new ChannelInitializer<SocketChannel>() {}) 

            //监听 7778 端口
            ChannelFuture future = bootstrap.bind(7778).sync();

            future.channel().closeFuture().sync();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

HttpServerHandler

java
public class HttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {                                             
                                                                                                                            
    // 读取客户端数据                                                                                                              
    @Override                                                                                                                
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {                               
        if (msg instanceof HttpRequest httpRequest) {
            //通过 uri 过滤特定资源                                                                                                 
            URI uri = new URI(httpRequest.uri());                                                                           
                                                                                                                            
            if ("/favicon.ico".equals(uri.getPath())) {                                                                     
                System.out.println("请求了 favicon.ico, 不需要返回");                                                               
                return;                                                                                                     
            }                                                                                                               
            
            // Unpooled 类是 Netty 提供的一个专门用于操作缓冲区的类
            ByteBuf content = Unpooled.copiedBuffer("hello,我是服务器", 
                    CharsetUtil.UTF_8);                                      
                                                                                                                            
            FullHttpResponse response = new DefaultFullHttpResponse(
                    HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);  
            
            //响应头信息设置
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, 
                    "text/plain;charset=utf-8");
            
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH, 
                    content.readableBytes());                                
                                                                                                                            
            ctx.writeAndFlush(response);                                                                                    
        }                                                                                                                   
    }                                                                                                                       
}

ServerInitializer

java
public class ServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        //向管道加入处理器
        socketChannel.pipeline()
                //编码处理器
                .addLast("MyHttpServerCodec", new HttpServerCodec())
                //自定义的 Http 响应处理器
                .addLast("MyHttpServerHandler",new HttpServerHandler());
    }

}

一个 Channel 包含了一个 ChannelPipelineChannelPipeline 中维护了一个由 ChannelHandlerContext 组成的双向链表

  • 入站事件会从链表 head 往后传递到最后一个入站的 handler
  • 出站事件从 tail 往前传递到第一个出站 handler

ChannelPipeline.png

  • 浏览器访问,发现成功响应

Http案例响应.png