使用Netty实现HTTP服务器
关键字:使用Netty实现HTTP服务器,使用Netty实现httpserver,Netty Http server
Netty是一个异步事件驱动的网络应用程序框架用于快速开发可维护的高性能协议服务器和客户端。Netty经过精心设计,具有丰富的协议,如FTP,SMTP,HTTP以及各种二进制和基于文本的传统协议。
Java程序员在开发web应用的时候,截止2018年大多数公司采用的还是servlet规范的那一套来开发的,比如springmvc。虽然在2018年Java程序员们可以选择使用spring5中的webflux,但是这个转变没那么快。然而,基于servlet那一套的springmvc性能很差,如果你厌烦了,你大可以使用netty来实现一个web框架。假设你想使用netty来实现,那么第一步你得会使用Netty启动一个HTTP服务器,下面开始吧。
Netty系列的文章在这里https://www.cnblogs.com/demingblog/p/9912099.html
本文HttpServer的实现目标
本文只是为了演示如何使用Netty来实现一个HTTP服务器,如果要实现一个完整的,那将是十分复杂的。所以,我们只实现最基本的,请求-响应。具体来说是这样的:
1. 启动服务
2. 客户端访问服务器,如:http://localhost:8081/index
3. 服务器返回 : 你请求的uri为:/index
创建server
netty 的api设计非常好,具有通用性,几乎就是一个固定模式的感觉。server端的启动和客户端的启动代码十分相似。启动server的时候指定初始化器,在初始化器中,我们可以放一个一个的handler,而具体业务逻辑处理就是放在这一个个的handler中的。写好的server端代码如下:
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;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.net.InetSocketAddress;
/**
* netty server
* 2018/11/1.
*/
public class HttpServer {
int port ;
public HttpServer(int port){
this.port = port;
}
public void start() throws Exception{
ServerBootstrap bootstrap = new ServerBootstrap();
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup work = new NioEventLoopGroup();
bootstrap.group(boss,work)
.handler(new LoggingHandler(LogLevel.DEBUG))
.channel(NioServerSocketChannel.class)
.childHandler(new HttpServerInitializer());
ChannelFuture f = bootstrap.bind(new InetSocketAddress(port)).sync();
System.out.println(" server start up on port : " + port);
f.channel().closeFuture().sync();
}
}
server端代码就这么多,看起来很长,但是这就是一个样板代码,你需要着重留意的就是childHandler(new HttpServerInitializer());
这一行。如果你对netty还不是十分熟悉,那么你不需要着急把每一行的代码都看懂。这段代码翻译成可以理解的文字是这样的:
1.bootstrap为启动引导器。
2.指定了使用两个时间循环器。EventLoopGroup
3.指定使用Nio模式。(NioServerSocketChannel.class)
4.初始化器为HttpServerInitializer
server启动代码就是这么多,我们注意看 HttpServerInitializer
做了什么。
在HttpServerInitializer 中添加server配置
HttpServerInitializer
其实就是一个ChannelInitializer
,在这里我们可以指定我们的handler。前面我们说过handler是用来承载我们具体逻辑实现代码的地方,我们需要在ChannelInitializer
中加入我们的特殊实现。代码如下:
public class HttpServerInitializer extends ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast(new HttpServerCodec());// http 编解码
pipeline.addLast("httpAggregator",new HttpObjectAggregator(512*1024)); // http 消息聚合器 512*1024为接收的最大contentlength
pipeline.addLast(new HttpRequestHandler());// 请求处理器
}
}
上面代码很简单,需要解释的点如下:
1. channel 代表了一个socket.
2. ChannelPipeline 就是一个“羊肉串”,这个“羊肉串”里边的每一块羊肉就是一个 handler.
handler分为两种,inbound handler,outbound handler 。顾名思义,分别处理 流入,流出。
3. HttpServerCodec 是 http消息的编解码器。
4. HttpObjectAggregator是Http消息聚合器,Aggregator这个单次就是“聚合,聚集”的意思。http消息在传输的过程中可能是一片片的消息片端,所以当服务器接收到的是一片片的时候,就需要HttpObjectAggregator来把它们聚合起来。
5. 接收到请求之后,你要做什么,准备怎么做,就在HttpRequestHandler中实现。
httpserver处理请求
上面的展示了 server端启动的代码,然后又展示了 server端初始化器的代码。下面我们来看看,请求处理的handler的代码:
public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
//100 Continue
if (is100ContinueExpected(req)) {
ctx.write(new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1,
HttpResponseStatus.CONTINUE));
}
// 获取请求的uri
String uri = req.uri();
Map<String,String> resMap = new HashMap<>();
resMap.put("method",req.method().name());
resMap.put("uri",uri);
String msg = "<html><head><title>test</title></head><body>你请求uri为:" + uri+"</body></html>";
// 创建http响应
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1,
HttpResponseStatus.OK,
Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8));
// 设置头信息
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");
//response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
// 将html write到客户端
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}
}
上面代码的意思,我用注释标明了,逻辑很简单。无论是FullHttpResponse
,还是 ctx.writeAndFlush
都是netty的api,看名知意即可。半蒙半猜之下,也可以看明白这个handler其实是:1 .获取请求uri,2. 组装返回的响应内容,3. 响应对融到客户端。需要解释的是100 Continue的问题:
100 Continue含义
HTTP客户端程序有一个实体的主体部分要发送给服务器,但希望在发送之前查看下服务器是否会接受这个实体,所以在发送实体之前先发送了一个携带100 Continue的Expect请求首部的请求。
服务器在收到这样的请求后,应该用 100 Continue或一条错误码来进行响应。
启动Http服务器,演示效果
上面的代码写完了,看的再多,不如运行起来跑一把。上面的3个类已经包含了我们目标中的服务端的完整代码。我们只需要在main函数中将其启动即可,代码如下:
public class Application {
public static void main(String[] args) throws Exception{
HttpServer server = new HttpServer(8081);// 8081为启动端口
server.start();
}
}
运行这个main函数,在浏览器中访问:http://localhost:8081/index ,http://localhost:8081/text/test 试试看吧。
至此,我们基于Netty的简易的Http服务器实现了(如果可以称作“HTTP服务器”的话)。 假如我们想要实现,访问 /index.html
就返回index.html
页面,访问/productList
就返回“商品列表JSON”,那么我们还需要做请求路由,还要加入JSON序列化支持,还要根据不同的请求类型调整HTTP响应头。本篇就不做展开了,本篇的目标是为了试下一个最简单的Http服务器。源码下载
使用Netty实现HTTP服务器
Netty实现心跳机制
Netty开发redis客户端,Netty发送redis命令,netty解析redis消息
Netty系列
spring如何启动的?这里结合spring源码描述了启动过程
SpringMVC是怎么工作的,SpringMVC的工作原理
spring 异常处理。结合spring源码分析400异常处理流程及解决方法
Mybatis Mapper接口是如何找到实现类的-源码分析
使用Netty实现HTTP服务器的更多相关文章
- 基于Netty打造RPC服务器设计经验谈
自从在园子里,发表了两篇如何基于Netty构建RPC服务器的文章:谈谈如何使用Netty开发实现高性能的RPC服务器.Netty实现高性能RPC服务器优化篇之消息序列化 之后,收到了很多同行.园友们热 ...
- Netty进行RPC服务器的开发 需要考虑的问题
谈谈如何使用Netty开发实现高性能的RPC服务器 - Newland - 博客园 http://www.cnblogs.com/jietang/p/5615681.html 如何实现.基于什么原理? ...
- Netty构建游戏服务器(一)--基本概念与原理
一,Netty是什么 1,Netty是由 JBOSS提供的一个 java开源框架. 2,Netty是JAR包,一般使用ALL-IN-ONE的JAR包就可以开发了. 3,Netty不需要运行在Tomca ...
- 【Netty】Netty简介及服务器客户端简单开发流程
什么是Netty Netty是一个基于Java NIO的编写客服端服务器的框架,是一个异步事件框架. 官网https://netty.io/ 为什么选择Netty 由于JAVA NIO编写服务器的过程 ...
- netty系列之:使用netty搭建websocket服务器
目录 简介 netty中的websocket websocket的版本 FrameDecoder和FrameEncoder WebSocketServerHandshaker WebSocketFra ...
- Netty——简单创建服务器、客户端通讯
Netty 是一个基于NIO的客户.服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用.Netty相当简化和流线化了网络应用的编程开发过程 ...
- 漫谈Java IO之 Netty与NIO服务器
前面介绍了基本的网络模型以及IO与NIO,那么有了NIO来开发非阻塞服务器,大家就满足了吗?有了技术支持,就回去追求效率,因此就产生了很多NIO的框架对NIO进行封装--这就是大名鼎鼎的Netty. ...
- netty搭建Tcp服务器实践
在netty基本组件介绍中,我们大致了解了netty的一些基本组件,今天我们来搭建一个基于netty的Tcp服务端程序,通过代码来了解和熟悉这些组件的功能和使用方法. 首先我们自己创建一个Server ...
- Netty构建Http服务器
Netty 是一个基于 JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞.基于事件驱动.高性能.高可靠性和高可定制性.换句话说,Netty是一个NIO框架,使用它可以简单快速地开发网络 ...
随机推荐
- 什么是GPIO?
”通用输入/输出口”(GPIO)是一个灵活的由软件控制的数字信号.他们可由多种芯片提供,且对于从事嵌入式和定制硬件的Linux开发者来说是比较熟 悉.每个GPIO都代表一个连接到特定引脚或球栅阵列(B ...
- LVS负载均衡NAT模式实现
LVS负载均衡之NAT模式配置 NAT 模式架构图: 操作步骤 实验环境准备:(centos7平台) 所有服务器上配置 # systemctl stop firewalld //关闭防火墙 # sed ...
- server.xml配置介绍
server.xml位于$TOMCAT_HOME/conf目录下,是Tomcat中最重要的配置文件,server.xml的每一个元素都对应了Tomcat中的一个组件:通过对xml文件中元素的配置,可以 ...
- rs(0)与rs("字段名")的区别
rs(0)与rs("字段名")的区别 注意:rs是RecordSet对象 前者是按sqlyu语句读出来的记录急的先后顺序命名的, rs(0)就是你select ...
- 移动开发day1_过渡_2d转换_3d立体
今天是就业班开班的第一天,上完了一天的课,做点总结. 什么叫做移动web 专门在手机或者 平板电脑 浏览器网页 为什么要学习移动web 工资高 1. 人拥有的手机数 大于 电脑的个数 2. 微信 1. ...
- .net core引用错误的Entity Framework而导致不能正常迁移数据的解决办法
本人刚学.net core,因此在学习过程中会遇上许许多多的坑.每一位初学者最大的问题在于资料的查看不仔细或是没有正确理解里面的内容,导致在后面自己在不知道错误的情况下做了一个小动作.对于完全没有理解 ...
- Eclipse——如何设置代码字体大小
eclipse默认字体太小,1920*1080下分辨不清楚,接下来介绍一下如何更改默认字体大小: 1.window-Preferences 2.General-Appearance-Colors an ...
- mysql将表数据导出为txt或csv文件
语法:select 字段 from 表名 into outfile 路径 示例txt:select * from stu_class into outfile './stu_class.text'; ...
- 移动端1px问题处理方法
在做移动端开发时,设计师提供的视觉稿一般是750px,当你定义 border-width:1px 时,在iphone6手机上却发现:边框变粗了.. 这是因为,1px是相对于750px的(物理像素),而 ...
- Centos环境下安装mongoDB
安装前注意: 此教程是通过yum安装的.仅限64位centos系统 安装步骤: 1.创建仓库文件: vi /etc/yum.repos.d/mongodb-org-3.4.repo 然后复制下面配置, ...