运用Netty3或Netty4公布Http协议服务

 现在是二〇一八年1三月14日18:12分,已经是下班时间了,小Alan后天给咱们不难的介绍一下Netty,让我们从此在采纳到Netty的时候能够有早晚的询问和基础,那样浓密学习Netty以及现在灵活使用那门技术也就不在话下了,万丈高楼平地起,程序猿们平常或许要侧重积累,多花些时日在技能方面,假如实在对代码提不起兴趣就早点布置好团结的向上路子,死磕着也没怎么须求,对团结没啥好处,可是要是您足足不讨厌编制程序,那么如故多多学习啊!

 

Netty是什么

Netty提供异步的、事件驱动的互联网应用程序框架和工具,用以急忙支付高品质、高可相信性的互连网服务器和客户端程序。

 

Netty的架构

Java 1

 

Netty的特性

设计:

——统一的API,适用于分化的商议(阻塞和非阻塞)

——基于灵活、可扩大的事件驱动模型

——中度可定制的线程模型

——可相信的无连接数据Socket援救(UDP)

性能:

Java,——更好的吞吐量,低顺延

——更省能源

——尽量减少不供给的内部存款和储蓄器拷贝

安全:

——完整的SSL/TLS和STARTTLS的支持

——能在Applet与谷歌(谷歌(Google))Android的范围条件运维卓越

健壮性:

——不再因过快、过慢或超负载连接导致OutOfMemoryError

——不再有在飞速网络环境下NIO读写频率差异的难点

易用:

——完善的Java doc,用户指南和样例

——简洁简单

——仅依靠于JDK1.5

 

Netty怎么用

小Alan教大家利用Netty3或Netty4公布Http协议服务接口,来指引迷天津大学家进入Netty的世界。

Netty3兑现Http协议服务接口步骤:

先是步:创立Http业务处理服务类,代码如下

 1 package com.alanlee.http;
 2 
 3 import static org.jboss.netty.handler.codec.http.HttpResponseStatus.OK;
 4 import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1;
 5 
 6 import org.jboss.netty.buffer.ChannelBuffer;
 7 import org.jboss.netty.buffer.DynamicChannelBuffer;
 8 import org.jboss.netty.channel.Channel;
 9 import org.jboss.netty.channel.ChannelFuture;
10 import org.jboss.netty.channel.ChannelFutureListener;
11 import org.jboss.netty.channel.ChannelHandlerContext;
12 import org.jboss.netty.channel.ExceptionEvent;
13 import org.jboss.netty.channel.MessageEvent;
14 import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
15 import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
16 import org.jboss.netty.handler.codec.http.HttpRequest;
17 import org.jboss.netty.handler.codec.http.HttpResponse;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20 
21 /**
22  * HTTP服务业务处理类.
23  * 
24  * @author AlanLee
25  * @version 2018/01/11
26  * 
27  */
28 public class HttpServerHandler extends SimpleChannelUpstreamHandler
29 {
30 
31     /**
32      * 日志类.
33      */
34     protected static final Logger LOGGER = LoggerFactory.getLogger(HttpServerHandler.class);
35 
36     @Override
37     public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception
38     {
39 
40         HttpRequest request = (HttpRequest) e.getMessage();
41         String method = request.getMethod().getName();
42         String url = request.getUri().toLowerCase();
43         System.out.println(method);
44         System.out.println(url);
45         
46         // 接收请求内容并打印
47         ChannelBuffer buffer = request.getContent();
48         String requestStr = new String(buffer.array(), "UTF-8");
49         System.out.println(requestStr);
50 
51         // 处理响应消息
52         HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
53         ChannelBuffer responseBuffer = new DynamicChannelBuffer(2048);
54         responseBuffer.writeBytes("你是猪吗?".getBytes("UTF-8"));
55         response.setContent(responseBuffer);
56         // 返回内容的MIME类型
57         response.setHeader("Content-Type", "text/html; charset=UTF-8");
58         // 响应体的长度
59         response.setHeader("Content-Length", response.getContent().writerIndex());
60         Channel ch = e.getChannel();
61 
62         // 响应给客户端
63         ChannelFuture f = ch.write(response);
64 
65         // 数据发送完毕,则关闭连接通道.
66         f.addListener(new ChannelFutureListener()
67         {
68             public void operationComplete(ChannelFuture future) throws Exception
69             {
70                 future.getChannel().close();
71             }
72         });
73     }
74 
75     /**
76      * 发生异常
77      */
78     @Override
79     public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
80     {
81         LOGGER.error("exceptionCaught(): ", e.getCause());
82         e.getCause().printStackTrace();
83     }
84 
85 }

第①步:创建Http管道类工厂用来统一Http业务处理服务类,代码如下

 1 package com.alanlee.http;
 2 
 3 import org.jboss.netty.channel.ChannelPipeline;
 4 import org.jboss.netty.channel.ChannelPipelineFactory;
 5 import org.jboss.netty.channel.Channels;
 6 import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
 7 import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
 8 
 9 /**
10  * HTTP管道类工厂.
11  * 
12  * @author AlanLee
13  * @version 2018/01/11
14  *
15  */
16 public class ServerPipelineFactory implements ChannelPipelineFactory
17 {
18 
19     /**
20      * 获取管道.
21      * 
22      * @return ChannelPipeline 管道
23      */
24     public ChannelPipeline getPipeline()
25     { 
26         ChannelPipeline pipeline = Channels.pipeline();
27         System.out.println("initChannel pipeline");
28         // 解码
29         pipeline.addLast("decoder", new HttpRequestDecoder(1024, 1024, 1000 * 1024));
30         // 编码
31         pipeline.addLast("encoder", new HttpResponseEncoder());
32         // 请求的业务类
33         pipeline.addLast("handler", new HttpServerHandler());
34         return pipeline;
35     }
36 
37 }

末段,让我们利用Netty3来公布Http协议服务接口,代码如下

 1 package com.alanlee.http;
 2 
 3 import java.net.InetSocketAddress;
 4 import java.util.concurrent.Executors;
 5 
 6 import org.jboss.netty.bootstrap.ServerBootstrap;
 7 import org.jboss.netty.channel.ChannelFactory;
 8 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
 9 
10 /**
11  * http服务启动类
12  * 
13  * @author AlanLee
14  * @version 2018/01/11
15  *
16  */
17 public class HttpServer
18 {
19 
20     public static void main(String[] args)
21     {
22         ChannelFactory factory = new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),
23                 Executors.newCachedThreadPool());
24         // 初始化channel的辅助类
25         ServerBootstrap bootstrap = new ServerBootstrap(factory);
26         bootstrap.setPipelineFactory(new ServerPipelineFactory());
27         // 创建服务器端channel的辅助类,接收connection请求
28         bootstrap.bind(new InetSocketAddress(8080));
29         System.out.println("Start http server success!");
30     }
31 }

 

Netty4完成Http协议服务接口步骤:

先是步:创造Http业务处理服务类,代码如下

 1 package com.alanlee.netty2;
 2 
 3 import io.netty.buffer.ByteBuf;
 4 import io.netty.buffer.Unpooled;
 5 import io.netty.channel.ChannelHandlerContext;
 6 import io.netty.channel.SimpleChannelInboundHandler;
 7 import io.netty.handler.codec.http.DefaultFullHttpResponse;
 8 import io.netty.handler.codec.http.FullHttpRequest;
 9 import io.netty.handler.codec.http.HttpHeaderNames;
10 import io.netty.handler.codec.http.HttpHeaderValues;
11 import io.netty.handler.codec.http.HttpHeaders;
12 import io.netty.handler.codec.http.HttpResponseStatus;
13 import io.netty.handler.codec.http.HttpVersion;
14 import io.netty.util.AsciiString;
15 
16 /**
17  * HttpServer业务处理
18  * 
19  * @author AlanLee
20  * @version 2018/01/11
21  *
22  */
23 public class HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest>
24 {
25 
26     private AsciiString contentType = HttpHeaderValues.TEXT_PLAIN;
27 
28     @Override
29     protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception
30     {
31         String method = msg.method().name(); // 请求方式
32         String url = msg.uri().toLowerCase(); // 请求路径
33         System.out.println(method);
34         System.out.println(url);
35 
36         // 接收请求内容并打印
37         ByteBuf byteBuf = msg.content();
38         byte[] bytes = new byte[byteBuf.readableBytes()];
39         byteBuf.readBytes(bytes);
40         String requestStr = new String(bytes, "UTF-8");
41         System.out.println(requestStr);
42 
43         DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
44                 Unpooled.wrappedBuffer("你才是猪!".getBytes()));
45 
46         HttpHeaders heads = response.headers();
47         // 返回内容的MIME类型
48         heads.add(HttpHeaderNames.CONTENT_TYPE, contentType + "; charset=UTF-8");
49         // 响应体的长度
50         heads.add(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
51         // 表示是否需要持久连接
52         heads.add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
53 
54         // 响应给客户端
55         ctx.write(response);
56     }
57 
58     /**
59      * 数据发送完毕,则关闭连接通道.
60      */
61     @Override
62     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception
63     {
64         System.out.println("channelReadComplete");
65         super.channelReadComplete(ctx);
66         ctx.flush();
67     }
68 
69     /**
70      * 发生异常
71      */
72     @Override
73     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
74     {
75         System.out.println("exceptionCaught");
76         if (null != cause)
77             cause.printStackTrace();
78         if (null != ctx)
79             ctx.close();
80     }
81 
82 }

最后,让大家运用Netty4来公布Http协议服务接口,代码如下

 1 package com.alanlee.netty2;
 2 
 3 import io.netty.bootstrap.ServerBootstrap;
 4 import io.netty.channel.ChannelInitializer;
 5 import io.netty.channel.ChannelOption;
 6 import io.netty.channel.nio.NioEventLoopGroup;
 7 import io.netty.channel.socket.SocketChannel;
 8 import io.netty.channel.socket.nio.NioServerSocketChannel;
 9 import io.netty.handler.codec.http.HttpObjectAggregator;
10 import io.netty.handler.codec.http.HttpRequestDecoder;
11 import io.netty.handler.codec.http.HttpResponseEncoder;
12 
13 /**
14  * 搭建HttpServer
15  * 
16  * @author Alanlee
17  * @version 2018/01/11
18  *
19  */
20 public class HttpServer
21 {
22 
23     private final int port;
24 
25     public HttpServer(int port)
26     {
27         this.port = port;
28     }
29 
30     public static void main(String[] args) throws InterruptedException
31     {
32         new HttpServer(8081).start();
33         System.out.println("Start http server success!");
34     }
35 
36     public void start() throws InterruptedException
37     {
38         // 初始化channel的辅助类
39         ServerBootstrap b = new ServerBootstrap();
40         NioEventLoopGroup group = new NioEventLoopGroup();
41         b.group(group).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>()
42         {
43             /**
44              * 初始化channel
45              */
46             @Override
47             protected void initChannel(SocketChannel ch) throws Exception
48             {
49                 System.out.println("initChannel ch:" + ch);
50                 // 获取管道
51                 ch.pipeline().addLast("decoder", new HttpRequestDecoder())  // 解码
52                         .addLast("encoder", new HttpResponseEncoder())      // 编码
53                         /* aggregator,消息聚合器(重要)。
54                         Netty4中为什么能有FullHttpRequest这个东西,
55                         就是因为有他,HttpObjectAggregator,如果没有他,
56                         就不会有那个消息是FullHttpRequest的那段Channel,
57                         同样也不会有FullHttpResponse,HttpObjectAggregator(512 * 1024)的参数含义是消息合并的数据大小,
58                         如此代表聚合的消息内容长度不超过512kb。*/
59                         .addLast("aggregator", new HttpObjectAggregator(512 * 1024))
60                         .addLast("handler", new HttpHandler()); // 请求的业务类
61             }
62 
63         }).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE);
64 
65         // 创建服务器端channel的辅助类,接收connection请求
66         b.bind(port).sync();
67     }
68 
69 }

 

查实成果

咱俩得以因而运转Netty3以及Netty4对应的HttpServer中的main方法来运维大家的Http服务器模拟。

运转Netty3提供的Http协议服务器,结果如下:

Java 2

起步成功以往,大家选择Postman工具来做个大约的测试,注意那里Netty3使用的是8080端口,结果如下:

Java 3

操纵台出口内容如下:

Java 4

 

我们再来运营Netty4提供的Http协议服务器,结果如下:

Java 5

起步成功之后,大家选拔Postman工具来做个简易的测试,注意那里Netty4使用的是8081端口,结果如下:

 Java 6

决定台出口内容如下:

Java 7

 

如此,我们就成功的应用了Netty3和Netty4宣布了Http协议服务接口,是还是不是很接近于大家的web后端开发,在平常的干活中假诺境遇要求高并发的类型屡次会需求将品种拆成后台节点来开发,此时可不只web端需求提供接口,后台节点也是须求提供接口的,那时Netty就正好符合供给,所以大家能够花些时间去控制Netty,建议控制Netty4版本,那样版本升级的改动量会小很多,那里小Alan给我们开了扇门,把您推荐门,修行在个人,假如您是三个热爱Java开发的人,也足以私聊Alan多多交换,只要艾伦空闲的时候。

 

甘休语:时间是最公平的,活一天就持有24时辰,差异只是讲求。你若不正视努力和时段,时光一定首先个辜负你。有希望就霎时行动,因为后天过的每一日,都以余生中最年轻的一天。

 

可爱博主:AlanLee

博客地址:http://www.cnblogs.com/AlanLee

本文来源腾讯网,欢迎我们进入腾讯网。

 

相关文章