Netty4 学习笔记之四: Netty HTTP服务的实现
前言
目前主流的JAVA web 的HTTP服务主要是 springMVC和Struts2,更早的有JSP/servlet。
在学习Netty的时候,发现Netty 也可以作HTTP服务,于是便将此整理一篇博文,分享给大家。
开发准备
添加配置
将Netty作为HTTP服务,需要在过滤器中添加HttpRequest之类的配置,如:
ph.addLast("encoder",new HttpResponseEncoder());
ph.addLast("decoder",new HttpRequestDecoder());
ph.addLast("aggregator", new HttpObjectAggregator(10*1024*1024));
基本配置和之前的客户端和服务端通信Demo几乎一样,就是在业务处理器中略微的修改下业务逻辑处理就可以了。
HTTP GET请求测试
那么进行测试。
首先启动Netty服务,然后使用HTTP GET 方式测试(直接在浏览器上输入http://localhost:6789/test)
结果如下:
HTTP服务准备
一般来说,使用HttpRequest 类作为请求,但是该类中没有获取消息体的方法,获取消息体的类为HttpContent 或LastHttpContent,这样获取请求和消息体则相当不对不方便。
在查阅Netty相关资料后,发现这样一个请求类,可以完成上述所提的要求。这个类就是FullHttpRequest。
查看该类源码,可以发现该类继承HttpRequest, FullHttpMessage,而FullHttpMessage又继承LastHttpContent, 而LastHttpContent又继承HttpContent,所以该类可以实现上述要求。
源码示例图:
那么代码修改如下:
FullHttpRequest httpRequest = (FullHttpRequest)msg;
String path=httpRequest.uri(); //获取路径
String body = getBody(httpRequest); //获取参数
HttpMethod method=httpRequest.method();//获取请求方法
然后测试POST、PUT和DELETE请求并使用json格式传输。
我们可以通过postman等工具来直接调用,就不用写相关请求代码了
可以看见,Netty 作为HTTP服务可以接受基本的请求。
完整的代码如下:
服务端:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
*
* Title: NettyServer
* Description: Netty服务端 Http测试
* Version:1.0.0
* @author pancm
* @date 2017年10月26日
*/
public class NettyServer {
private static final int port = 6789; //设置服务端端口
private static EventLoopGroup group = new NioEventLoopGroup(); // 通过nio方式来接收连接和处理连接
private static ServerBootstrap b = new ServerBootstrap();
/**
* Netty创建全部都是实现自AbstractBootstrap。
* 客户端的是Bootstrap,服务端的则是 ServerBootstrap。
**/
public static void main(String[] args) throws InterruptedException {
try {
b.group(group);
b.channel(NioServerSocketChannel.class);
b.childHandler(new NettyServerFilter()); //设置过滤器
// 服务器绑定端口监听
ChannelFuture f = b.bind(port).sync();
System.out.println("服务端启动成功,端口是:"+port);
// 监听服务器关闭监听
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully(); //关闭EventLoopGroup,释放掉所有资源包括创建的线程
}
}
}
服务端过滤器:
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
/**
*
* Title: NettyServerFilter
* Description: Netty 服务端过滤器
* Version:1.0.0
* @author pancm
* @date 2017年10月26日
*/
public class NettyServerFilter extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline ph = ch.pipeline();
//处理http服务的关键handler
ph.addLast("encoder",new HttpResponseEncoder());
ph.addLast("decoder",new HttpRequestDecoder());
ph.addLast("aggregator", new HttpObjectAggregator(10*1024*1024));
ph.addLast("handler", new NettyServerHandler());// 服务端业务逻辑
}
}
服务端业务逻辑
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;
import java.net.InetAddress;
/**
*
* Title: NettyServerHandler
* Description: 服务端业务逻辑
* Version:1.0.0
* @author pancm
* @date 2017年10月26日
*/
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
private String result="";
/*
* 收到消息时,返回信息
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if(! (msg instanceof FullHttpRequest)){
result="未知请求!";
send(ctx,result,HttpResponseStatus.BAD_REQUEST);
return;
}
FullHttpRequest httpRequest = (FullHttpRequest)msg;
try{
String path=httpRequest.uri(); //获取路径
String body = getBody(httpRequest); //获取参数
HttpMethod method=httpRequest.method();//获取请求方法
//如果不是这个路径,就直接返回错误
if(!"/test".equalsIgnoreCase(path)){
result="非法请求!";
send(ctx,result,HttpResponseStatus.BAD_REQUEST);
return;
}
System.out.println("接收到:"+method+" 请求");
//如果是GET请求
if(HttpMethod.GET.equals(method)){
//接受到的消息,做业务逻辑处理...
System.out.println("body:"+body);
result="GET请求";
send(ctx,result,HttpResponseStatus.OK);
return;
}
//如果是POST请求
if(HttpMethod.POST.equals(method)){
//接受到的消息,做业务逻辑处理...
System.out.println("body:"+body);
result="POST请求";
send(ctx,result,HttpResponseStatus.OK);
return;
}
//如果是PUT请求
if(HttpMethod.PUT.equals(method)){
//接受到的消息,做业务逻辑处理...
System.out.println("body:"+body);
result="PUT请求";
send(ctx,result,HttpResponseStatus.OK);
return;
}
//如果是DELETE请求
if(HttpMethod.DELETE.equals(method)){
//接受到的消息,做业务逻辑处理...
System.out.println("body:"+body);
result="DELETE请求";
send(ctx,result,HttpResponseStatus.OK);
return;
}
}catch(Exception e){
System.out.println("处理请求失败!");
e.printStackTrace();
}finally{
//释放请求
httpRequest.release();
}
}
/**
* 获取body参数
* @param request
* @return
*/
private String getBody(FullHttpRequest request){
ByteBuf buf = request.content();
return buf.toString(CharsetUtil.UTF_8);
}
/**
* 发送的返回值
* @param ctx 返回
* @param context 消息
* @param status 状态
*/
private void send(ChannelHandlerContext ctx, String context,HttpResponseStatus status) {
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, Unpooled.copiedBuffer(context, CharsetUtil.UTF_8));
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}
/*
* 建立连接时,返回消息
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("连接的客户端地址:" + ctx.channel().remoteAddress());
ctx.writeAndFlush("客户端"+ InetAddress.getLocalHost().getHostName() + "成功与服务端建立连接! ");
super.channelActive(ctx);
}
}
结语
那么Netty HTTP 服务的相关测试就到这了,如果有什么疑问,欢迎讨论!
该项目我放在github上了,有兴趣的可以看看!https://github.com/xuwujing/Netty
Netty4 学习笔记之四: Netty HTTP服务的实现的更多相关文章
- Netty4 学习笔记之一:客户端与服务端通信 demo
前言 因为以前在项目中使用过Mina框架,感受到了该框架的强大之处.于是在业余时间也学习了一下Netty.因为Netty的主要版本是Netty3和Netty4(Netty5已经被取消了),所以我就直接 ...
- Oracle学习笔记之四sp1,Oracle 11g的常用函数
从Oracle学习笔记之四,SQL语言入门中摘出来的,独立成一章节 3.1 字符类函数 ASCII(c)和CHR(i) 分别用于返回一个字符的ASCII码和返回给定ASCII值所对应的字符. C ...
- Netty学习笔记(二)——netty组件及其用法
1.Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. 原生NIO存在的问题 1) NIO的类库和API繁杂,使用麻烦:需要熟练掌握Selector.Se ...
- 多线程编程学习笔记——异步调用WCF服务
接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...
- Binder学习笔记(九)—— 服务端如何响应Test()请求 ?
从服务端代码出发,TestServer.cpp int main() { sp < ProcessState > proc(ProcessState::self()); sp < I ...
- Django 学习笔记之四 QuerySet常用方法
QuerySet是一个可遍历结构,它本质上是一个给定的模型的对象列表,是有序的. 1.建立模型: 2.数据文件(test.txt) 3.文件数据入库(默认的sqlite3) 入库之前执行 数据库同步命 ...
- Netty4 学习笔记之三:粘包和拆包
前言 在上一篇Netty 心跳 demo 中,了解了Netty中的客户端和服务端之间的心跳.这篇就来讲讲Netty中的粘包和拆包以及相应的处理. 名词解释 粘包: 会将消息粘粘起来发送.类似吃米饭,一 ...
- 【Visual C++】游戏编程学习笔记之四:透明动画实现
本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44224963 作者:ZeeCod ...
- Oracle学习笔记之四,SQL语言入门
1. SQL语言概述 1.1 SQL语言特点 集合性,SQL可以的高层的数据结构上进行工作,工作时不是单条地处理记录,而对数据进行成组的处理. 统一性,操作任务主要包括:查询数据:插入.修改和删除数据 ...
随机推荐
- python、java和php的百度指数对比
Python: Python是纯粹的自由软件, 源代码和解释器CPython遵循 GPL(GNU General Public License)协议.Python语法简洁清晰,特色之一是强制用空白符( ...
- linux进程资源占用高原因分析命令记录
1.查看进程的线程: ps -eLf|egrep 'gateserver|UID' 2.跟踪线程调用: strace -p 15530 3.统计线程中函数的调用小号CPU时间: strace -p 1 ...
- Azure ASM虚拟机部署“安全扩展”
Azure虚拟机,默认情况下没有安装杀毒软件.如果您有此需求可以通过Azure 扩展进行安装,有关Azure反恶意软件的官方说明请参考:https://docs.azure.cn/zh-cn/secu ...
- 【翻译】.Net Core的意义
想要了解.Net Core的意义,就必须要了解拥有很长历史的.Net Framework,.Net Framework1.0于2002年发布.从那开始,每隔两年就会有一个主版本推出.伴随着Visual ...
- Ajax 跨域 异步 CORS
HTTP access control (CORS) 核心在于使用定制(添加新的header)HTTP header让浏览器和服务器有更多的相互了解,从而决定一个请求或者响应成功还是失败 对于一个 ...
- 解决mysql启动失败报1067错误
最近做项目使用 mysql 数据库 ,因为卸载了鲁大师造成了数据库文件缺失.重装mysql数据库后启动出现了1067错误,详情如下 在网上查了错误原因,将my.ini文件下的默认搜索引擎换成了 myi ...
- 一:配置使用阿里云Maven库
鉴于国内的网络环境,从默认 Maven 库下载 jar 包是非常的痛苦. 速度慢就不说了,还经常是下不下来,然后一运行就是各种 ClassNotFoundException,然后你得找到残留文件删掉重 ...
- Spring的69个知识点
目录 Spring 概述 依赖注入 Spring beans Spring注解 Spring数据访问 Spring面向切面编程(AOP) Spring MVC Spring 概述 1. 什么是spri ...
- PEP8
1.规则要求 https://www.python.org/dev/peps/pep-0008 2.工具 https://github.com/jcrocholl/pep8 3.基本使用方法 测试自己 ...
- JAVA提高十三:Hashtable&Properties深入分析
最近因为一些琐碎的事情,导致一直没时间写博客,正好今天需求开发完的早,所以趁早写下本文,本文主要学习的是Hashtable的分析,因为上面一篇文章研究的是HashMap,而Hashtable和Hash ...