netty实现HTTP服务器

注:更多netty相关文章请访问博主专栏: netty专栏

概述

目前主流的Java web服务器还是采用springboot+Tomcat来实现的,底层还是基于servlet开发的。servlet不是异步的,所以性能并不是很理性,无法满足当下的快速服务器的要求。

目前spring5已经实现了基于reactor的webflux异步编程(响应式编程),springboot2.X也已经支持webflux,性能会提升很多。其底层实现就是netty。

要想更深入了解响应式编程,请移步至笔者博客:java9 响应式编程支持,里面包含什么是响应式编程,reactor基本讲解以及在springboot中使用响应式编程。

因此netty不仅仅可以作为组件的通信,还可以作为HTTP服务器使用 ,接下来我们就看看如何使用netty实现HTTP服务器。

本文只是简单使用netty搭建HTTP服务器,功能不够完善,不可以用于生产服务。

HTTP服务器代码实现

编写一个HTTPserver服务类。

public class MyHttpServer {
    int port ;
    public MyHttpServer(int port){
        this.port = port;
    }

    public void start() throws Exception{
        ServerBootstrap bootstrap = new ServerBootstrap();
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup work = new NioEventLoopGroup();
        try {
            bootstrap.group(boss, work)
                    .handler(new LoggingHandler(LogLevel.DEBUG))
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new HttpServerInitializer());

            ChannelFuture f = bootstrap.bind(new InetSocketAddress(port)).sync();
            System.out.println("http server started . port : " + port);
            f.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception{
        MyHttpServer server = new MyHttpServer(8080);// 8080为启动端口
        server.start();
    }
}

class HttpServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();
        pipeline.addLast(new HttpServerCodec());// http 编解码
        pipeline.addLast("httpAggregator",new HttpObjectAggregator(512*1024)); // http 消息聚合器                                                                     512*1024为接收的最大contentlength
        pipeline.addLast(new HttpRequestHandler());// 请求处理器

    }
}

上面代码主要看HttpServerInitializer这个类。
ChannelPipeline中依次添加了HttpServerCodec,HttpObjectAggregator 和 HttpRequestHandler

  • HttpServerCodec 是HTTP消息的编解码器。HttpServerCodec是HttpRequestDecoderHttpResponseEncoder的组合类,用于简化HTTP编程。
  1. HttpRequestDecoder 即把 ByteBuf 解码到 HttpRequest 和 HttpContent。
  2. HttpResponseEncoder 即把 HttpResponse 或 HttpContent 编码到 ByteBuf。
    在这里插入图片描述
  • HttpObjectAggregator 作用是HTTP消息聚合,将多个消息转换为单一的FullHttpRequest和FullHttpResponse。因为HttpServerCodec解码器在每个HTTP消息中会生产多个对象:HttpRequest、HttpResponse、HttpContent、LastHttpContent。
    HttpObjectAggregator 是负责多个chunk的http 请求和响应的。他让我们的handler 处理看到的是一个完整的fullHttpResponse,不需要考虑是Content 是否是 LastHttpContent,netty的LastHttpContent代表body结束部分。一个chunk 代表一个HttpContent,最后一个chunk 由 LastHttpContent 表示。

  • HttpRequestHandler 是我们的业务逻辑处理类。

请求处理类HttpRequestHandler :

class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) {
        // 获取请求的uri
        String uri = req.uri();
        Map<String,String> resMap = new HashMap<>();
        resMap.put("method",req.method().name());
        resMap.put("uri",uri);
        String msg = "<html><head><title>test</title></head><body>你请求uri为:" + uri+"</body></html>";
        // 创建http响应
        FullHttpResponse response = new DefaultFullHttpResponse(
                HttpVersion.HTTP_1_1,
                HttpResponseStatus.OK,
                Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8));
        // 设置头信息
        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");
        //response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
        // 将html write到客户端
        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
    }
}

很简单,就是读取请求URL,回复客户端一个字符串。

验证

启动服务
在这里插入图片描述
浏览器访问 localhost:8080/任意字符串。比如:http://localhost:8080/index1/q

在浏览器页面中返回:

你请求uri为:/index1/q

注:更多netty相关文章请访问博主专栏: netty专栏

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页
实付 9.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值