Netty实现Http服务器
Netty是一个异步事件驱动的网络应用程序框架用于快速开发和可维护的高性能协议服务器和客户端。Netty经过精心设计,具有丰富的协议,如FTP,SMTP,HTTP以及各种二进制和基于文本的传统协议。
Java程序员在开发web应用的时候,截止2018年大多数公司采用的还是servlet规范的那一套来开发的,比如springmvc。虽然在2018年Java程序员们可以选择使用spring5中的webflux,但是这个转变没那么快。然而,基于servlet那一套的springmvc性能很差,可以使用netty来实现一个web框架。使用Netty实现一个简单的HTTP服务器。
1、搭建环境
1
2 1implementation 'io.netty:netty-all:4.1.43.Final'
2
2、server
netty的api设计非常好,具有通用性,几乎就是一个固定模式的感觉。server端的启动和客户端的启动代码十分相似。启动server的时候指定初始化器,在初始化器中,我们可以放一个一个的handler,而具体业务逻辑处理就是放在这一个个的handler中的。写好的server端代码如下:
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 1public class TestServer {
2
3 public static void main(String[] args){
4 //循环组接收连接,不进行处理,转交给下面的线程组
5 EventLoopGroup bossGroup = new NioEventLoopGroup();
6 //循环组处理连接,获取参数,进行工作处理
7 EventLoopGroup workerGroup = new NioEventLoopGroup();
8 try {
9 //服务端进行启动类
10 ServerBootstrap serverBootstrap = new ServerBootstrap();
11 //使用NIO模式,初始化器等等
12 serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new TestServerInitializer());
13 //绑定端口
14 ChannelFuture channelFuture = serverBootstrap.bind(9000).sync();
15 channelFuture.channel().closeFuture().sync();
16 } catch (InterruptedException e) {
17 e.printStackTrace();
18 } finally {
19 bossGroup.shutdownGracefully();
20 workerGroup.shutdownGracefully();
21 }
22 }
23}
24
25
注意:childHandler(new TestServerInitializer()) TestServerInitializer是自定义的Channel的处理器。
3、serverInitializer
在这里可以指定我们的handler,handler是用来承载我们具体逻辑实现代码的地方,我们需要在ChannelInitializer中加入我们的具体的业务实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 1public class TestServerInitializer extends ChannelInitializer<SocketChannel> {
2
3 //连接注册,创建成功,会被调用
4 @Override
5 protected void initChannel(SocketChannel ch) throws Exception {
6 //通道
7 ChannelPipeline pipeline = ch.pipeline();
8 //http的编解码
9 pipeline.addLast("httpServerCodec",new HttpServerCodec());
10 //http消息聚合器
11 //Aggregator这个单次就是“聚合,聚集”的意思。http消息在传输的过程中可能是一片片的消息片端,所以当服务器接收到的是一片片的时候,就需要HttpObjectAggregator来把它们聚合起来。
12 pipeline.addLast("httpAggregator",new HttpObjectAggregator(512*1024));
13 //自定义处理器(具体实现逻辑)
14 pipeline.addLast("testHttpServerHandler",new TestHttpServerHandler());
15
16 }
17}
18
4、具体请求处理
读取channel里面的信息,进行处理之后,进行返回数据。
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
52
53
54
55
56 1public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
2
3 private Log LOGGER = LogFactory.getLog(TestHttpServerHandler.class);
4
5 //具体处理,读取客户端发过来的请求,把响应进行返回
6 @Override
7 protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
8 LOGGER.info("channel read");
9 if(msg instanceof HttpRequest){
10 //响应内容,和编码处理
11 ByteBuf content = Unpooled.copiedBuffer("Hello World", CharsetUtil.UTF_8);
12 //http协议版本,响应状态,和内容
13 FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,content);
14 //设置响应头
15 response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
16 response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());
17 //刷新缓冲区,并输出
18 ctx.writeAndFlush(response);
19 ctx.channel().close();
20 }
21 }
22
23
24 @Override
25 public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
26 LOGGER.info("channel unregistered");
27 super.channelUnregistered(ctx);
28 }
29
30 @Override
31 public void channelInactive(ChannelHandlerContext ctx) throws Exception {
32 LOGGER.info("channel inactive");
33 super.channelInactive(ctx);
34 }
35
36 @Override
37 public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
38 LOGGER.info("channel registered");
39 super.channelRegistered(ctx);
40 }
41
42 @Override
43 public void channelActive(ChannelHandlerContext ctx) throws Exception {
44 LOGGER.info("channel active");
45 super.channelActive(ctx);
46 }
47
48
49 @Override
50 public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
51 LOGGER.info("channel readComplete");
52 super.channelReadComplete(ctx);
53 }
54}
55
56
5、启动测试
、