Netty学习(四)- 基于Netty的HTTP协议栈应用

前言

HTTP服务器在我们日常开发中,常见的实现方式就是实现一个Java Web项目,基于Nginx+Tomcat的方式就可以提供HTTP服务。但是很多场景是非Web容器的场景,这个时候再使用Tomcat就大材小用了。这个时候就可以使用基于Netty的HTTP协议。那么基于Netty开发的HTTP服务器有什么优势呢?

  • Netty的多线程模型和异步非阻塞特性能够支持高并发;
  • 相比于Tomcat HTTP,Netty HTTP更加轻量、小巧、可靠,占用资源更少。

一、HTTP协议简介

1、HTTP协议介绍
HTTP协议:HyperText Transfer Protocol,超文本传输协议;标准的Client/Server模型,是应用层的协议,由请求和响应组成,客户端指定URL并且携带必要参数后就可以请求服务器。

HTTP URL(特殊的URI)格式:
http://host[:port][abs_path]

  • http表示通过HTTP协议定位网络资源;
  • host表示合法的Internet主机域或者IP地址;
  • port指定端口号,默认使用80;
  • abs_path表示指定资源的URI;

2、HTTP请求消息
HTTP协议一般包含三个部分:

  • 请求行
  • 消息头
  • 空格行(一般在POST请求中)
  • 请求正文(一般在POST请求中)

(1)GET请求
GET请求一般由请求行和消息头组成,请求参数放在url后面,用?连接。

请求行格式为: method /request uri/HTTP version
消息头由键值对组成。
输入百度,通过抓包可以看到如下GET请求组成:
在这里插入图片描述

(2)POST请求
POST请求参数一般放在请求正文(message body)中。
在这里插入图片描述
图片来源:https://blog.csdn.net/xiao__gui/article/details/16981245

二、Netty 中HTTP编解码器介绍

1、Netty中HTTP编解码器介绍

(1)HttpRequestDecoder
Decodes ByteBuf into HttpRequest and HttpContent.
Http请求消息解码器,即将ByteBuf解码到HttpRequest和HttpContent中。

(2)HttpResponseEncoder
Encodes an HttpResponse or an HttpContent into a ByteBuf.
响应编码器,即将HttpResponse 或 HttpContent 编码到 ByteBuf。

(3)HttpServerCodec
A combination of HttpRequestDecoder and HttpResponseEncoder which enables easier server side HTTP implementation.
即同时实现了HttpRequestDecoder和HttpResponseEncoder的功能,所以基于Netty实现HTTP服务端时,在ChannelPipeline中加上HttpServerCodec,或者HttpResponseEncoder和HttpServerCodec即可。

ch.pipeline().addLast("httpServerCodec", new HttpServerCodec());

或者
ch.pipeline().addLast("httpRequestDecoder", new HttpRequestDecoder())
            .addLast("httpResponseEncoder",new  HttpResponseEncoder());

(4)HttpObjectAggregator
A ChannelHandler that aggregates an HttpMessage and its following HttpContent into a single FullHttpRequest or FullHttpResponse (depending on if it used to handle requests or responses) with no following HttpContent. It is useful when you don't want to take care of HTTP messages whose transfer encoding is 'chunked'.

HttpObjectAggregator 可以把HttpMessage和HttpContent聚合成一个FullHttpRequest或FullHttpResponse(处理请求或响应)。
在解析POST请求时,由于参数放在message body中,上述3种解码器无法解析,所以必须用HttpObjectAggregator。

2、HTTP GET解析

(1) 获取GET请求uri
HTTP请求参数是放在uri中,所以拿到uri再进行解析即可,需要注意,浏览器发请求时会同时去请求favicon.ico(url左侧的图标),需要过滤该请求。
在这里插入图片描述

// 获取uri
HttpRequest request = (HttpRequest)msg;
String uri = request.uri();

// 过滤favicon.ico请求
if(uri.equals("favicon.ico")) {
   
    return;
}

(2) 解析uri
QueryStringDecoder用来解析uri,它的作用是将请求中的参数分割成path和k-v键值对的形式,也可以用来解码 Content-Type = “application/x-www-form-urlencoded” 的 HTTP POST请求,但是只能用一次。

如uri为"/hello?recipient=world&x=1;y=2",使用QueryStringDecoder解析后:
path:/hello
key1:recipient, value1:world
key2:x, value2: 1
key3: y, value3: 2

解析代码:

String uri = request.uri();
HttpMethod method = request.method();
if (HttpMethod.GET.equals(method)) {
   
    QueryStringDecoder queryStringDecoder = new QueryStringDecoder(uri, Charsets.toCharset(CharEncoding.UTF_8));
    Map<String, List<String>> uriAttrMap = queryStringDecoder.parameters();
     if (uriAttrMap != null && uriAttrMap.size() > 0) {
      
       uriAttrMap.entrySet().stream().forEach(entry -> {
                           entry.getValue().stream().forEach(attrVal -> {
   
               System.out.println("key : " + entry.getKey() + ", value : " + attrVal);
          });
        });
     }
 }
3、 HTTP POST 解析实践

HTTP POST请求参数在message body中,需要使用HttpObjectAggregator进行解码。
POST请求中常见的content-type有application/json、application/x-www-form-urlencoded、 multipart/form-data,下面针对不同content-type进行解析。

(1)解析 application/json
JSON格式解析较为简单,将msg转换为FullHttpRequest后,获取content反序列化成JSONObject对象即可拿到参数值。

FullHttpRequest fullHttpRequest = (FullHttpRequest) msg;
String jsonStr = fullHttpRequest.content().toString(Charsets.toCharset(CharEncoding.UTF_8));
JSONObject json = JSONObject.parseObject(jsonStr);
json.entrySet().stream().forEach(entry -> {
   
     System.out.println(entry.getKey() + " = " + entry.getValue().toString());
});

(2)解析 application/x-www-form-urlencoded
以POST提交请求的时候,不设置enctype属性,默认值即为application/x-www-form-urlencoded
①可以使用上节说到的QueryStringDecoder进行解析,解析代码如前所述;
②使用HttpPostRequestDecoder进行解析。
HttpPostRequestDecoder既可以解析application/x-www-form-urlencoded,又可以解析multipart/form-data。
解析代码如下:

HttpRequest request = (HttpRequest) msg;
HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(factory, request, Charsets.toCharset(CharEncoding.UTF_8));
List<InterfaceHttpData> httpDatas = decoder.getBodyHttpDatas();
httpDatas.forEach(data -> {
   
    if (InterfaceHttpData.HttpDataType.Attribute.
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值