[Netty] Netty案例——基于Netty的HTTP请求

使用Netty实现HTTP请求

使用Netty编写服务端,使用浏览器模拟HTTP请求,访问服务端。服务端返回的数据在浏览器显示。

服务端代码

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class TestService {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            // 创建bootstrap启动服务器
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).childHandler(new TestServiceInitializer());

            // 绑定端口启动服务器
            ChannelFuture channelFuture = bootstrap.bind(8181).sync();

            channelFuture.channel().closeFuture().sync();

        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

添加ChannelInitializer

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;

public class TestServiceInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        // 向管道加入处理器
        // 得到管道
        ChannelPipeline pipeline = socketChannel.pipeline();

        // 加入一个netty提供的httpServerCoder编解码器
        pipeline.addLast("myHttpServerCodec",new HttpServerCodec());

        // 增加自定义处理器
        pipeline.addLast("MyTestHttpServiceHandler",new TestHttpServiceHandler());

    }
}

自定义处理器

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

/**
 * SimpleChannelInboundHandler 是 ChannelInboundHandlerAdapter
 * 泛型内,HttpObject为返回的数据类型
 */
public class TestHttpServiceHandler extends SimpleChannelInboundHandler<HttpObject> {


    // 读取客户端数据
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        if (msg instanceof HttpRequest) {
            System.out.println("客户端地址"+ ctx.channel().remoteAddress());
            // 回复HTTP请求
            ByteBuf content = Unpooled.copiedBuffer("服务器发送数据", CharsetUtil.UTF_8);
            // 构造一个http的响应,即httpResponse
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());

            // 将构建好的response发送出去
            ctx.writeAndFlush(response);
        }
    }
}

结果

使用浏览器调用,在浏览器看到服务器的返回数据,服务端可以看到前后建立了两次连接。
在这里插入图片描述
通过F12可以看到,确实存在两次请求,一次是期望的请求,另一次是请求浏览器图标。
在这里插入图片描述
使用资源过滤完成请求的排除

HttpRequest request = (HttpRequest) msg;
URI uri = new URI(request.uri());
if ("/favicon.ico".equals(uri.getPath())){
    // 过去处理
    return;
}

版权声明:本文为GxDong_原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。