netty 实现http请求,post上传数据为json数据

最近导师安排个项目,硬件设备是利用http post的方式向服务器发送数据,原来一直是用java自带的http请求进行编码的,但是考虑到该项目后续会有高并发的问题,就采用了netty的方式来实现http server端。大家如果对netty不太熟悉的同学可以去看《netty权威指南》,链接走起~~~https://pan.baidu.com/s/1jnVoKWhL4TQiIg15gpFlkQ

由于书中和一般网上的例子基本都有各自依赖的场景,我的场景是http发送的是post请求,然后data是用json格式表示的。
接下来,我和大家大致介绍一下如何用netty来构建一个简单的http server端。

首先我们需要引入使用netty所依赖的包(另外提醒大家,如果在netty开发中遇到了一些异常,可以考虑替换一下netty包的版本)

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.33.Final</version>
</dependency>

创建一个HttpServer来启动服务,并且绑定端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

/*
* 用netty实现httpServer
*/
public class HttpServer {

public void start(int port) throws Exception {
//配置服务端的NIO线程组,一个用于服务端接受客户端的连接,另一个用于进行sokcetchannel的网络读写
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();

try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 1024).childHandler(
new ChildChannelHandler()).childOption(ChannelOption.SO_KEEPALIVE, true);

//绑定端口,b是一个boss线程,负责处理来自端口的socket请求
ChannelFuture f = b.bind(port).sync();
//等待服务器监听端口关闭
f.channel().closeFuture().sync();

}finally {
//退出,释放线程池资源
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}

private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {

@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("http-decoder", new HttpRequestDecoder());
/**usually we receive http message infragment,if we want full http message,
* we should bundle HttpObjectAggregator and we can get FullHttpRequest。
* 我们通常接收到的是一个http片段,如果要想完整接受一次请求的所有数据,我们需要绑定HttpObjectAggregator,然后我们
* 就可以收到一个FullHttpRequest-是一个完整的请求信息。
**/
ch.pipeline().addLast("http-aggegator", new HttpObjectAggregator(65536));
ch.pipeline().addLast("servercodec",new HttpServerCodec());
ch.pipeline().addLast(new HttpProtobufServerHandler());
ch.pipeline().addLast("responseencoder",new HttpResponseEncoder());
}
}

public static void main(String[] args) throws Exception {
System.out.println("开始启动http服务器...");
new HttpServer().start(9000);
// TcpServer.shutdown();
}
}

大家注意一下,上面HttpRequestDecoder()、HttpServerCodec()、HttpResponseEncoder()都是netty自带的,是对数据进行编码和解码操作的。而HttpProtobufServerHandler()是自定义的类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class HttpProtobufServerHandler extends SimpleChannelInboundHandler<FullHttpRequest>{

public void channelActive(ChannelHandlerContext ctx) throws Exception {

}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
System.out.println(cause.getMessage() + " error");
ctx.close();
}

@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
ByteBuf jsonBuf = msg.content();
//将byte转换为json字符串,如果需要提取json对象,可以自己实现解析器
String jsonStr = jsonBuf.toString(CharsetUtil.UTF_8);
System.out.println(jsonStr);
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();
}
}

到目前为止,基于netty的httpServer就搭建完成了,我们可以启动项目,然后对 http://127.0.0.1:9000 发起post请求,然后看到返回的数据为”你好!!!”

感谢你对我的支持 让我继续努力分享有用的技术和知识点.