使用Netty3或Netty4发布Http协议服务
现在是2018年1月11日18:12分,已经是下班时间了,小Alan今天给大家简单的介绍一下Netty,让大家以后在使用到Netty的时候能够有一定的了解和基础,这样深入学习Netty以及以后灵活应用这门技术也就不在话下了,万丈高楼平地起,程序猿们平时还是要注重积累,多花些时间在技术上面,如果实在对代码提不起兴趣就早点规划好自己的发展路线,死磕着也没什么必要,对自己没啥好处,但是如果你至少不讨厌编程,那么还是多多学习吧!
Netty是什么
Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
Netty的架构
Netty的特性
设计:
------统一的API,适用于不同的协议(阻塞和非阻塞)
------基于灵活、可扩展的事件驱动模型
------高度可定制的线程模型
------可靠的无连接数据Socket支持(UDP)
性能:
------更好的吞吐量,低延迟
------更省资源
------尽量减少不必要的内存拷贝
安全:
------完整的SSL/TLS和STARTTLS的支持
------能在Applet与谷歌Android的限制环境运行良好
健壮性:
------不再因过快、过慢或超负载连接导致OutOfMemoryError
------不再有在高速网络环境下NIO读写频率不一致的问题
易用:
------完善的Java doc,用户指南和样例
------简洁简单
------仅依赖于JDK1.5
Netty怎么用
小Alan教大家使用Netty3或Netty4发布Http协议服务接口,来引导大家进入Netty的世界。
Netty3实现Http协议服务接口步骤:
第一步:创建Http业务处理服务类,代码如下
package com.alanlee.http; import static org.jboss.netty.handler.codec.http.HttpResponseStatus.OK;
import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1; import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.DynamicChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
* HTTP服务业务处理类.
*
* @author AlanLee
* @version 2018/01/11
*
*/
public class HttpServerHandler extends SimpleChannelUpstreamHandler
{ /**
* 日志类.
*/
protected static final Logger LOGGER = LoggerFactory.getLogger(HttpServerHandler.class); @Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception
{ HttpRequest request = (HttpRequest) e.getMessage();
String method = request.getMethod().getName();
String url = request.getUri().toLowerCase();
System.out.println(method);
System.out.println(url); // 接收请求内容并打印
ChannelBuffer buffer = request.getContent();
String requestStr = new String(buffer.array(), "UTF-8");
System.out.println(requestStr); // 处理响应消息
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
ChannelBuffer responseBuffer = new DynamicChannelBuffer(2048);
responseBuffer.writeBytes("你是猪吗?".getBytes("UTF-8"));
response.setContent(responseBuffer);
// 返回内容的MIME类型
response.setHeader("Content-Type", "text/html; charset=UTF-8");
// 响应体的长度
response.setHeader("Content-Length", response.getContent().writerIndex());
Channel ch = e.getChannel(); // 响应给客户端
ChannelFuture f = ch.write(response); // 数据发送完毕,则关闭连接通道.
f.addListener(new ChannelFutureListener()
{
public void operationComplete(ChannelFuture future) throws Exception
{
future.getChannel().close();
}
});
} /**
* 发生异常
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
{
LOGGER.error("exceptionCaught(): ", e.getCause());
e.getCause().printStackTrace();
} }
第二步:创建Http管道类工厂用来联结Http业务处理服务类,代码如下
package com.alanlee.http; import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder; /**
* HTTP管道类工厂.
*
* @author AlanLee
* @version 2018/01/11
*
*/
public class ServerPipelineFactory implements ChannelPipelineFactory
{ /**
* 获取管道.
*
* @return ChannelPipeline 管道
*/
public ChannelPipeline getPipeline()
{
ChannelPipeline pipeline = Channels.pipeline();
System.out.println("initChannel pipeline");
// 解码
pipeline.addLast("decoder", new HttpRequestDecoder(1024, 1024, 1000 * 1024));
// 编码
pipeline.addLast("encoder", new HttpResponseEncoder());
// 请求的业务类
pipeline.addLast("handler", new HttpServerHandler());
return pipeline;
} }
最后,让我们利用Netty3来发布Http协议服务接口,代码如下
package com.alanlee.http; import java.net.InetSocketAddress;
import java.util.concurrent.Executors; import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; /**
* http服务启动类
*
* @author AlanLee
* @version 2018/01/11
*
*/
public class HttpServer
{ public static void main(String[] args)
{
ChannelFactory factory = new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
// 初始化channel的辅助类
ServerBootstrap bootstrap = new ServerBootstrap(factory);
bootstrap.setPipelineFactory(new ServerPipelineFactory());
// 创建服务器端channel的辅助类,接收connection请求
bootstrap.bind(new InetSocketAddress(8080));
System.out.println("Start http server success!");
}
}
Netty4实现Http协议服务接口步骤:
第一步:创建Http业务处理服务类,代码如下
package com.alanlee.netty2; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.AsciiString; /**
* HttpServer业务处理
*
* @author AlanLee
* @version 2018/01/11
*
*/
public class HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest>
{ private AsciiString contentType = HttpHeaderValues.TEXT_PLAIN; @Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception
{
String method = msg.method().name(); // 请求方式
String url = msg.uri().toLowerCase(); // 请求路径
System.out.println(method);
System.out.println(url); // 接收请求内容并打印
ByteBuf byteBuf = msg.content();
byte[] bytes = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(bytes);
String requestStr = new String(bytes, "UTF-8");
System.out.println(requestStr); DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
Unpooled.wrappedBuffer("你才是猪!".getBytes())); HttpHeaders heads = response.headers();
// 返回内容的MIME类型
heads.add(HttpHeaderNames.CONTENT_TYPE, contentType + "; charset=UTF-8");
// 响应体的长度
heads.add(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
// 表示是否需要持久连接
heads.add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); // 响应给客户端
ctx.write(response);
} /**
* 数据发送完毕,则关闭连接通道.
*/
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception
{
System.out.println("channelReadComplete");
super.channelReadComplete(ctx);
ctx.flush();
} /**
* 发生异常
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
{
System.out.println("exceptionCaught");
if (null != cause)
cause.printStackTrace();
if (null != ctx)
ctx.close();
} }
最后,让我们利用Netty4来发布Http协议服务接口,代码如下
package com.alanlee.netty2; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder; /**
* 搭建HttpServer
*
* @author Alanlee
* @version 2018/01/11
*
*/
public class HttpServer
{ private final int port; public HttpServer(int port)
{
this.port = port;
} public static void main(String[] args) throws InterruptedException
{
new HttpServer(8081).start();
System.out.println("Start http server success!");
} public void start() throws InterruptedException
{
// 初始化channel的辅助类
ServerBootstrap b = new ServerBootstrap();
NioEventLoopGroup group = new NioEventLoopGroup();
b.group(group).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>()
{
/**
* 初始化channel
*/
@Override
protected void initChannel(SocketChannel ch) throws Exception
{
System.out.println("initChannel ch:" + ch);
// 获取管道
ch.pipeline().addLast("decoder", new HttpRequestDecoder()) // 解码
.addLast("encoder", new HttpResponseEncoder()) // 编码
/* aggregator,消息聚合器(重要)。
Netty4中为什么能有FullHttpRequest这个东西,
就是因为有他,HttpObjectAggregator,如果没有他,
就不会有那个消息是FullHttpRequest的那段Channel,
同样也不会有FullHttpResponse,HttpObjectAggregator(512 * 1024)的参数含义是消息合并的数据大小,
如此代表聚合的消息内容长度不超过512kb。*/
.addLast("aggregator", new HttpObjectAggregator(512 * 1024))
.addLast("handler", new HttpHandler()); // 请求的业务类
} }).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE); // 创建服务器端channel的辅助类,接收connection请求
b.bind(port).sync();
} }
检验成果
我们可以通过运行Netty3以及Netty4对应的HttpServer中的main方法来启动我们的Http服务器模拟。
启动Netty3提供的Http协议服务器,结果如下:
启动成功之后,我们利用Postman工具来做个简单的测试,注意这里Netty3使用的是8080端口,结果如下:
控制台输出内容如下:
我们再来启动Netty4提供的Http协议服务器,结果如下:
启动成功之后,我们利用Postman工具来做个简单的测试,注意这里Netty4使用的是8081端口,结果如下:
控制台输出内容如下:
这样,我们就成功的使用了Netty3和Netty4发布了Http协议服务接口,是不是很类似于我们的web后端开发,在平时的工作中如果遇到需要高并发的项目往往会需要将项目拆成后台节点来开发,此时可不仅仅web端需要提供接口,后台节点也是需要提供接口的,这时Netty就正好符合需求,所以大家可以花些时间去掌握Netty,建议掌握Netty4版本,这样版本升级的改动量会小很多,这里小Alan给大家开了扇门,把你引进门,修行在个人,如果你是一个热爱Java开发的人,也可以私聊Alan多多交流,只要Alan空闲的时候。
结束语:时间是最公平的,活一天就拥有24小时,差别只是珍惜。你若不相信努力和时光,时光一定第一个辜负你。有梦想就立刻行动,因为现在过的每一天,都是余生中最年轻的一天。
可爱博主:AlanLee
博客地址:http://www.cnblogs.com/AlanLee
本文出自博客园,欢迎大家加入博客园。
使用Netty3或Netty4发布Http协议服务的更多相关文章
- netty3升netty4一失眼成千古恨
老项目是netty3的,本来想直接改到netty5,但是netty5居然是只支持jdk1.7,很奇怪jdk1.6和jdk1.8都不行..为了兼容jdk1.6加上netty4本来和netty5就差别不大 ...
- Azure机器学习入门(四)模型发布为Web服务
接Azure机器学习(三)创建Azure机器学习实验,下一步便是真正地将Azure机器学习的预测模型发布为Web服务.要启用Web服务发布任务,首先点击底端导航栏的运行即"Run" ...
- 蓝萝卜blu netty3升netty4
老项目是netty3的,本来想直接改到netty5,但是netty5居然是只支持jdk1.7,很奇怪jdk1.6和jdk1.8都不行..为了兼容jdk1.6加上netty4本来和netty5就差别不大 ...
- ArcGIS API for JavaScript(2)-ArcGIS Server发布要素图层服务
1.前言 上一篇该系列的文章我们主要讲了一下基础Web地图搭建,这篇我们主要讲一下ArcGIS Server发布服务,并且如何调用服务.将自己的数据加载到Web地图当中来,实现Web端浏览数据. 2. ...
- 利用DotSpatial发布WMS, WFS服务
我们遇到的几个给政府部门做的GIS系统,一般都只要面子,只要好看,领导高兴得不得了,点点这里点点那里,哟,这按钮一点还会转,领导开心得跟朵花似的...要是搞个各种分析什么的全堆上来,他就嫌烦了...这 ...
- wcf通过webHttpBinding方式发布rest web服务
<system.serviceModel> <services> <service name="ServiceUpdater.ServiceUpdate&quo ...
- OpenLayers调用arcgis server发布的地图服务
有两种方式可以调用arcgis server发布的地图服务,一种是rest,一种是wms. 地图的投影为900913,arcgis server为10.0版本,地图服务的空间参考为3857. 与 ...
- OpenLayers调用ArcGIS Server发布的WFS服务
OpenLayers调用ArcGIS Server发布的WFS服务 原创: 蔡建良 2013-08-20 一. 开发环境 1) Openlayers2.13+arcgis server9.3 2) W ...
- geotrellis使用(三十一)使用geotrellis直接将GeoTiff发布为TMS服务
前言 传统上我们需要先将Tiff中存储的影像等数据先切割成瓦片,而后再对外提供服务.这样的好处是服务器响应快,典型的用空间来换时间的操作.然而这样造成的问题是空间的巨大浪费,一般情况下均需要存储1-1 ...
随机推荐
- stark - 5 ⇲ 其他常用功能
Ⅰ 排序 当数据量增多,对于数据 我们应该能够指定如何排序的.且此功能应该是可以给用户自定义进行配置的. 这是StarkHandler类的方法1 order_list = [] def get_ord ...
- MNIST手写数字识别 Tensorflow实现
def conv2d(x, W): return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME') 1. strides在官方定义中是一 ...
- Maven 安装jar文件到本地repository
Reference: https://maven.apache.org/general.html#importing-jars mvn install:install-file \ -Dfile=&l ...
- Tomcat服务器安装配置
1.到http://tomcat.apache.org/官网下载Tomcat的zip版本,这样直接解压就行了,不用安装.我下载是Tomcat6.0版本的zip文件,解压在D:\Java\apache- ...
- javac的命令(-Xbootclasspath、-classpath与-sourcepath等)
当编译源文件时,编译器常常需要识别出类型的有关信息.对于源文件中使用.扩展或实现的每个类或接口,编译器都需要其类型信息.这包括在源文件中没有明确提及.但通过继承提供信息的类和接口. 例如,当扩展 ja ...
- 在超链接href中实现form的提交
<form name="form1" method="post" action=""> <div class=" ...
- 常见的接口与类 -- Comparator
接口Comparator 1.1 前面我们讲过Java提供了一个用于比较的接口Comparable,提供了一个比较的方法,所有实现该接口的类,都动态的实现了该比较方法.实际上Java中除了比较一个接口 ...
- 使用jQuery实时监听input输入值的变化
//jQuery实时监听input值变化 $("#email").on("input propertychange",function(){ var str = ...
- 事务,约束,范式,视图,索引,pl/sql
1.操作分类: DML. DDL. DCL manipulation definition control 2.transction 事务 起始于DML,遇到 commit ,rollb ...
- 一些Android的博客,没事翻翻
深入剖析Android系统(推荐) 深入浅出Android系统移植与平台开发系列(推荐) Android系统开篇(小米工程师对系统的整体分析,推荐) Android6.0Framework源码解析系列 ...