Java Netty HTTP服务实现过程解析

 更新时间:2020年08月13日 09:31:36   作者:猿天地  
这篇文章主要介绍了Java Netty HTTP服务实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。

在后端开发中接触HTTP协议的比较多,目前大部分都是基于Servlet容器实现的Http服务,往往有一些核心子系统对性能的要求非常高,这个时候我们可以考虑采用NIO的网络模型来实现HTTP服务,以此提高性能和吞吐量,Netty除了开发网络应用非常方便,还内置了HTTP相关的编解码器,让用户可以很方便的开发出高性能的HTTP协议的服务,Spring Webflux默认是使用的Netty。

接下来我们简单的介绍下如何使用Netty来构建一个简单的Http服务

创建一个NettyHttpServer来启动服务

public static void main(String[] args) {
  int port = 2222;
  new NettyHttpServer().run(port);
}

public void run(int port) {
  EventLoopGroup bossGroup = new NioEventLoopGroup();
  EventLoopGroup workerGroup = new NioEventLoopGroup();
  ServerBootstrap bootstrap = new ServerBootstrap();
  bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
      .childHandler(new ChannelInitializer<SocketChannel>() {
        @Override
        public void initChannel(SocketChannel ch) throws Exception {
            ch.pipeline().addLast(
                new HttpResponseEncoder(),
                new HttpRequestDecoder(),
                new NettyHttpServerHandler());
        }
        }).option(ChannelOption.SO_BACKLOG, 128)
        .childOption(ChannelOption.SO_KEEPALIVE, true);
  try {
    ChannelFuture f = bootstrap.bind(port).sync();
    f.channel().closeFuture().sync();
  } catch (InterruptedException e) {
    e.printStackTrace();
  } finally {
    workerGroup.shutdownGracefully();
    bossGroup.shutdownGracefully();
  }
}

需要关注的是下面的这行代码:

ch.pipeline().addLast(
new HttpResponseEncoder(),
new HttpRequestDecoder(),
new NettyHttpServerHandler());

HttpResponseEncoder: 服务端往客户端发送数据的行为是Response,所以这边要使用HttpResponseEncoder将数据进行编码操作

HttpRequestDecoder:服务端接收到数据的行为是Request,所以要使用HttpRequestDecoder进行解码操作

NettyHttpServerHandler:自定义的数据处理类

public class NettyHttpServerHandler extends ChannelInboundHandlerAdapter {

public class NettyHttpServerHandler extends ChannelInboundHandlerAdapter {

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {  
    FullHttpResponse response = new DefaultFullHttpResponse(
        HttpVersion.HTTP_1_1, 
        HttpResponseStatus.OK,
        Unpooled.wrappedBuffer("欢迎来到猿天地".getBytes("utf-8")));
    response.headers().set(Names.CONTENT_TYPE, "text/plain;charset=UTF-8");
    response.headers().set(Names.CONTENT_LENGTH, response.content().readableBytes());
    response.headers().set(Names.CONNECTION, Values.KEEP_ALIVE);
    ctx.write(response);
    ctx.flush();
  }

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

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

}

通过DefaultFullHttpResponse构建了返回的对象,设置了HTTP版本,返回的状态码,返回的内容。

返回的响应头通过response.headers().set()进行设置。

到此为止,一个简单的HTTP服务就实现好了,我们启动服务,在浏览器中输入http://localhost:2222/ 就可以看到页面中显示的内容是:欢迎来到猿天地

上面演示的是一个典型的请求响应模式,一般我们开发接口的时候通常都是需要根据请求的参数进行对应的数据返回,如何在Netty中获取请求的参数呢?

channelRead方法中的msg参数就是请求信息,通过msg可以获取到请求的所有信息,有请求头信息(包括请求的地址,GET请求的参数),请求体(POST请求的数据)。

下面已GET请求的方式来获取请求的参数信息,代码如下:

if (msg instanceof HttpRequest) {
    DefaultHttpRequest request = (DefaultHttpRequest) msg;
    System.out.println("URI:" + request.getUri());
    System.err.println(msg);
}
if (msg instanceof HttpContent) {
    LastHttpContent httpContent = (LastHttpContent) msg;
    ByteBuf byteData = httpContent.content();
    if (byteData instanceof EmptyByteBuf) {
      System.out.println("Content:无数据");
    } else {
      String content = new String(ByteUtils.objectToByte(byteData));
      System.out.println("Content:" + content);
    }
}

重启服务,访问地址加上参数进行访问:http://localhost:2222/?name=yjh

可以看到控制台输出的内容就是一个完整的HTTP请求包含的信息:

URI:/?name=yjh
DefaultHttpRequest(decodeResult: success, version: HTTP/1.1)
GET /?name=yjh HTTP/1.1
Host: localhost:2222
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _ga=GA1.1.939107719.1520393952; JSESSIONID=EE205236911D5BBA145E3021DB472D90
Content:无数据

本文只是简单的介绍了如何在Netty中去实现HTTP服务,如果想要做成Spring MVC这样的框架那后面的路还很长,请求响应Netty内置了编解码器,还是有很多工作需要自己去做的。比如参数的获取,请求的路由,参数映射成对象等….

源码参考:https://github.com/yinjihuan/netty-im

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Spring Boot集成Swagger接口分类与各元素排序问题

    Spring Boot集成Swagger接口分类与各元素排序问题

    这篇文章主要介绍了Spring Boot集成Swagger接口分类与各元素排序问题,首先我们需要对Swagger中的接口也就是以Controller 层作为第一级梯度进行组织的,Controller在我们实际开发中,与其他具体接口之间是存在一对多的关系,本文给大家介绍的非常详细,需要的朋友参考下吧
    2023-10-10
  • java算法之静态内部类实现雪花算法

    java算法之静态内部类实现雪花算法

    这篇文章主要介绍了java算法之静态内部类实现雪花算法,对算法感兴趣的同学,一定要看一下
    2021-05-05
  • Java Metrics系统性能监控工具的使用详解

    Java Metrics系统性能监控工具的使用详解

    Metrics是一个Java库,可以对系统进行监控,统计一些系统的性能指标。本文就来和大家详细聊聊这个工具的具体使用,希望对大家有所帮助
    2022-11-11
  • Java发送邮件javax.mail的实现方法

    Java发送邮件javax.mail的实现方法

    这篇文章主要为大家介绍了Java发送邮件javax.mail的实现方法,具有一定的参考价值,代码都有详细的注释,感兴趣的小伙伴们可以参考一下
    2016-01-01
  • SpringBoot框架如何管理Xml和CSV

    SpringBoot框架如何管理Xml和CSV

    XML是可扩展标记语言,是一种用于标记电子文件使其具有结构性的标记语言。CSV是一种通用的、相对简单的文件格式,通常被用在大数据领域,进行大规模的数据搬运操作,本文将介绍SpringBoot框架如何管理Xml和CSV
    2021-06-06
  • java return用法实例详解

    java return用法实例详解

    在本篇文章里小编给大家整理的是关于java return用法以及相关知识点总结,需要的朋友们参考下。
    2019-08-08
  • SpringBoot 中 AutoConfiguration的使用方法

    SpringBoot 中 AutoConfiguration的使用方法

    这篇文章主要介绍了SpringBoot 中 AutoConfiguration的使用方法,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-04-04
  • Springboot和Jpa实现学生CRUD操作代码实例

    Springboot和Jpa实现学生CRUD操作代码实例

    这篇文章主要介绍了Springboot和Jpa实现学生CRUD操作代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • hbase访问方式之java api

    hbase访问方式之java api

    这篇文章主要介绍了hbase访问方式之java api,需要的朋友可以参考下
    2017-09-09
  • Springboot解决no main manifest attribute错误

    Springboot解决no main manifest attribute错误

    在开发Springboot项目时,使用java -jar命令运行jar包可能出现no main manifest attribute错误,本文就来介绍一下该错误的解决方法,感兴趣的可以了解一下
    2024-09-09

最新评论