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

用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请求每次一结束他就断掉了,重新访问就会产生一个新的做处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值