欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

用Netty搭建一个简单的Http服务器

程序员文章站 2024-01-20 16:06:16
用Netty搭建一个简单的Http服务器,实现客户端发起http请求时,服务端作出响应返回一串数据。准备工作搭建maven项目,引入netty的依赖。我这里用的是4.0.20版本。 io.netty netty-all 4.0.20.Final<...

用Netty搭建一个简单的Http服务器,实现客户端发起http请求时,服务端作出响应返回一串数据。

准备工作

搭建maven项目,引入netty的依赖。我这里用的是4.0.20版本。

   <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.0.20.Final</version>
   </dependency>

代码编写

1、启动服务端

public class HttpServer {


    public static void main(String[] args)  {

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

        try {
        	//设置启动参数
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                     //自定义childHandler =》 HttpChannelInitializer
                    .childHandler(new HttpChannelInitializer());

            //启动服务端
            ChannelFuture channelFuture = serverBootstrap.bind("127.0.0.1",8989).sync();
            channelFuture.addListener(new ChannelFutureListener() {
                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                    if (channelFuture.isSuccess()) {
                        System.out.println("服务器启动成功");
                    }else {
                        System.out.println("服务器启动失败");
                    }
                }
            });
            channelFuture.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

2、自定义childHandler,继承ChannelInitializer类

public class HttpChannelInitializer extends ChannelInitializer<SocketChannel> {

    protected void initChannel(SocketChannel socketChannel) throws Exception {
        //获取pipeline
        ChannelPipeline pipeline = socketChannel.pipeline();
        //HttpServerCodec:encode & decode
        pipeline.addLast(new HttpServerCodec());
        //自定义handler
        pipeline.addLast(new HttpChannelHandler());
    }
    
}

3、自定义请求处理类,继承SimpleChannelInboundHandler类,HttpObject是一个接口,有包括request和response等子类。

这里有一个问题,每次浏览器请求会带上一个favicon.ico图标的请求,我们可以通过得到的路径进行过滤。

public class HttpChannelHandler extends SimpleChannelInboundHandler<HttpObject> {


    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {

        //ctx里可以获取很多内容,比如客户端的ip
        System.out.println(ctx.channel().remoteAddress());

        if (msg instanceof HttpRequest) {
            HttpRequest request = (HttpRequest) msg;

            //过滤图标的请求
            if ("/favicon.ico".equals(request.getUri())) {
                System.out.println("不做处理");
                return;
            }
        }

        //给客户端回传数据
        ByteBuf byteBuf = Unpooled.copiedBuffer("hello~我是服务器~", CharsetUtil.UTF_8);
        //使用DefaultFullHttpResponse作为response
        DefaultFullHttpResponse response = new DefaultFullHttpResponse(
                HttpVersion.HTTP_1_1, HttpResponseStatus.OK, byteBuf);
        //设置头信息,以及编码,防止乱码
        response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain;charset=utf8");
        response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, byteBuf.readableBytes());

        //回写数据
        ctx.writeAndFlush(response);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        ctx.close();
    }
}

有几个问题需要注意一下。

1、不同的客户端进来,是同一个handler做处理吗?

2、每次刷新请求,还是之前的handler在做处理吗?

解答:
对handler的hashcode和Pipline的hashcode作出打印。
1、用两个浏览器请求同一个请求所得到的handler和Pipline的哈希是不同的。
2、浏览器一刷新,所得到的handler和Pipline的哈希也是不同的。
因为http请求每次一结束他就断掉了,重新访问就会产生一个新的做处理。

本文地址:https://blog.csdn.net/axiang_/article/details/107597803

相关标签: Java netty http