Netty学习笔记之一(Netty解析简单的Http Post Json 请求)

一,HTTP解码器可能会将一个HTTP请求解析成多个消息对象。

 ch.pipeline().addLast(new HttpServerCodec());
 ch.pipeline().addLast(new ParseRequestHandler());

经过HttpServerCodec解码之后,一个HTTP请求会导致:ParseRequestHandler的 channelRead()方法调用多次(测试时 "received message"输出了两次)

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        System.out.println("received message");

可以用HttpObjectAggregator 将多个消息转换为单一的一个FullHttpRequest,如下:

 ch.pipeline().addLast(new HttpServerCodec());
 ch.pipeline().addLast(new HttpObjectAggregator(65536));
 ch.pipeline().addLast(new ParseRequestHandler());

此时,一个HTTP消息(Object msg)是下面这样的。

HttpObjectAggregator$AggregatedFullHttpRequest(decodeResult: success, version: HTTP/1.1, content: CompositeByteBuf(ridx: 0, widx: 17, cap: 17, components=1))
POST / HTTP/1.1
Host: 127.0.0.1:8888
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: null
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 17
Cookie: _ga=GA1.1.457486782.1446782739
Connection: keep-alive

从上面可以看出,实体首部字段Content-Length是17,表明实体主体有17个字节。

而我发送的消息是这样的:

HTTP POST 请求,请求体是JSON格式的数据。这里使用的是json-lib解析的 Json字符串。代码如下:

    //parse job type 0,1
    private String getJobType(FullHttpRequest request) throws IOException{
        ByteBuf jsonBuf = request.content();
        String jsonStr = jsonBuf.toString(CharsetUtil.UTF_8);
        JSONObject jsonObj = JSONObject.fromObject(jsonStr);
        String jobType = jsonObj.getString("jobType");
        return jobType;
    }

需要注意是:使用json-lib解析Json字符串时,需要其他的依赖包如下:

解析完成之后,需要把处理后的结果发送到下一个ChannelHandler,进行下一步的处理。

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
    throws Exception {
        //do some process
 .....
        ctx.fireChannelRead(job);
}

注意,使用的是fireChannelRead()方法,而不是 ctx.writeAndFlush(...)。因为,writeAndFlush/write 是Outbound,它是把消息发送到上一个Handler,进而发送到remote peer,而这里是InBound。具体参考:

这里,通过 ctx.fireChannelRead(job); 将处理后的结果发送到下一个Channel处理。

 ch.pipeline().addLast(new HttpServerCodec());
 ch.pipeline().addLast(new HttpObjectAggregator(2048));
 ch.pipeline().addLast(new ParseRequestHandler());
 ch.pipeline().addLast(new OozieRequestHandler());

下一个Handler是OozieRequestHandler,它负责向Oozie Server提交作业,之后返回jobId给客户端(HttpServerCodec  Handler 负责底层传输细节)。

Netty构造一个http 响应的方法如下:

String jobId = doPost(jobConfig);
FullHttpResponse response = new DefaultFullHttpResponse(
                    HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
                    Unpooled.wrappedBuffer(jobId.getBytes()));

response.headers().set(CONTENT_TYPE, "application/xml");

response.headers().setInt(CONTENT_LENGTH,
                    response.content().readableBytes());
            ctx.write(response).addListener(ChannelFutureListener.CLOSE);
时间: 2024-10-24 08:30:49

Netty学习笔记之一(Netty解析简单的Http Post Json 请求)的相关文章

【web开发学习笔记】Structs2 Result学习笔记(一)简单介绍

Structs2 Result学习笔记(一)简单介绍 问题一 <struts> <constant name="struts.devMode" value="true" /> <package name="resultTypes" namespace="/r" extends="struts-default"> <action name="r1"

马程序员学习笔记——红黑树解析二

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 四.树中删除元素 1.先找到需要删除的元素. 2. 2.1如果被删元素没有子元素,那么直接用NIL节点代替他: 2.2如果被删元素只有一个子元素,那么直接用这个子元素代替他: 2.3如果被删元素有两个子元素,那么就用左子元素中的最大元素或者右子元素的最小元素代替他. 比如说原来要删除的元素是N,N有两个分支,其中P是N左分支中的最大元素,那么就

马程序员学习笔记——红黑树解析三

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 六.树的前序.中序.后序 前序遍历(根左右): 1.访问根节点 2.前序遍历左子树 3.前序遍历右子树 中序遍历(左根右): 1.中序遍历左子树 2.访问根节点 3.中序遍历右子树 后序遍历(左右根): 1.后序遍历左子树 2.后序遍历右子树 3.访问根节点 扩展:已知前序.中序遍历,求后序遍历? 例: 前序遍历: GDAFEMHZ 中序遍历:

[转载]SharePoint 2013搜索学习笔记之搜索构架简单概述

Sharepoint搜索引擎主要由6种组件构成,他们分别是爬网组件,内容处理组件,分析处理组件,索引组件,查询处理组件,搜索管理组件.可以将这6种组件分别部署到Sharepoint场内的多个服务器上,组成适合需求的Sharepoint搜索场,搜索场的体系结构设计主要参考量是爬网内容量,微软根据爬网内容量不同将搜索场分为大型场,中型场和小型场,更多详细信息可参考: SharePoint Server 2013 中的搜索概述和在SharePoint Server 2013 中规划企业搜索体系结构.

lua学习笔记10:lua简单命令行

前面多次用了命令行,这次就好好学下命令行: 一 格式 lua [options][script][args] 二 具体命令 -e 直接将命令传个lua -l 加载一个文件 -i 进入交互模式 例如,终端输入: lua -e "print(math.sin(12))" lua学习笔记10:lua简单命令行,布布扣,bubuko.com

c++学习笔记2(c++简单程序)

c++的简单程序 练习一: #include <iostream>int main(){std::cout<<"你好c++\n";int x;std::cin>>x;std::cout<<x;return 0;} #:预处理标志,对文本进行预处理操作:预处理标志表示该行代码要最先进行处理,要在编译器编译代码之前运行.include:预处理指令 表示将<>内的文件读入. <...>头文件iostream(输入输出流)

Sharepoint2013搜索学习笔记之搜索构架简单概述(一)

Sharepoint搜索引擎主要由6种组件构成,他们分别是爬网组件,内容处理组件,分析处理组件,索引组件,查询处理组件,搜索管理组件.可以将这6种组件分别部署到Sharepoint场内的多个服务器上,组成适合需求的Sharepoint搜索场,搜索场的体系结构设计主要参考量是爬网内容量,微软根据爬网内容量不同将搜索场分为大型场,中型场和小型场,更多详细信息可参考:SharePoint Server 2013 中的搜索概述和在SharePoint Server 2013 中规划企业搜索体系结构. S

马程序员学习笔记——红黑树解析四

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 本篇是将上面三篇的理论知识转化成代码,java实现 首先,看一下算法导论里的伪代码 一.左旋 The pseudocode for LEFT-ROTATE assumes that right[x] ≠ nil[T] and that the root's parent is nil[T].(伪代码的左旋方法中假设X的右孩子不为空) LEFT-

DuiLib学习笔记2——写一个简单的程序

我们要独立出来自己创建一个项目,在我们自己的项目上加皮肤这才是初衷.我的新建项目名为:duilibTest 在duilib根目录下面有个 Duilib入门文档.doc 我们就按这个教程开始入门 首先新建一个win32项目 去DuiLib根目录,把目录下DuiLib文件夹拷贝到新建项目的根目录.再把这个项目添加进我们解决方案中. 从教程里面把以下代码粘贴到我们项目的stdafx.h中 // Duilib使用设置部分 #pragma once #define WIN32_LEAN_AND_MEAN