Netty高级进阶之基于Netty的HTTP服务器开发
本通过实战演练,学习了如何基于 Netty 开发一个 HTTP 服务器。
介绍
Netty 的 HTTP 协议栈可靠性高,性能优异。相对于传统的 Tomcat、Jetty 等服务器,它更加轻量级和小巧,灵活性和定制型也更好。
功能需求
- Netty 服务器在 8080 端口监听
- 浏览器发出请求”http://localhost:8080“
- 服务器回复消息给客户端”你好,我是 Netty 服务器“,并对特定请求资源进行过滤
服务端代码实现
NettyHttpServer
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
57
58
59
60
61
62
63
64
65/**
* HTTP服务端
*
* @name: NettyHttpServer
* @author: terwer
* @date: 2022-04-27 22:23
**/
public class NettyHttpServer {
private int port;
public NettyHttpServer(int port) {
this.port = port;
}
public void run() throws InterruptedException {
NioEventLoopGroup bossGroup = null;
NioEventLoopGroup workerGroup = null;
try {
// 1. 创建bossGroup线程组: 处理网络事件--连接事件,默认是2*处理器线程数目
bossGroup = new NioEventLoopGroup(1);
// 2. 创建workerGroup线程组: 处理网络事件--读写事件,默认是2*处理器线程数目
workerGroup = new NioEventLoopGroup();
// 3. 创建服务端启动助手
ServerBootstrap serverBootstrap = new ServerBootstrap();
// 4. 设置bossGroup线程组和workerGroup线程组
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128) // 5. 设置服务端通道实现为NIO
.childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE) // 6. 参数设置,设置活跃状态,child是设置workerGroup
.childHandler(new ChannelInitializer<SocketChannel>() { // 7. 创建一个通道初始化对象
protected void initChannel(SocketChannel ch) throws Exception {
// 8. 向pipeline中添加自定义业务处理handler
// 自定义处理类
ch.pipeline().addLast(new HttpServerCodec());
ch.pipeline().addLast(new NettyHttpServerHandler());
}
});
// 9. 启动服务端并绑定端口,同时将异步改为同步
ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
System.out.println("HTTP服务器启动成功");
channelFuture.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
System.out.println("端口绑定成功!");
} else {
System.out.println("端口绑定失败!");
}
}
});
// 10. 关闭通道和关闭连接池(不是真正关闭,只是设置为关闭状态)
channelFuture.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws InterruptedException {
new NettyHttpServer(8080).run();
}
}HTTP 处理类
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/**
* HTTP处理类
*
* @name: NettyHttpServerHandler
* @author: terwer
* @date: 2022-04-29 01:07
**/
public class NettyHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
/**
* 读取就绪事件
*
* @param ctx
* @param msg
* @throws Exception
*/
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
// 1.判断是否是HTTP请求
if (msg instanceof HttpRequest) {
DefaultHttpRequest request = (DefaultHttpRequest) msg;
System.out.println("浏览器请求路径:" + request.uri());
// 2.响应浏览器
ByteBuf byteBuf = Unpooled.copiedBuffer("<h1>你好,我是Netty服务端</h1>", CharsetUtil.UTF_8);
DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, byteBuf);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=utf-8");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, byteBuf.readableBytes());
ctx.writeAndFlush(response);
}
}
}运行效果
过滤掉图标
1
2
3
4
5// 图标不响应
if("/favicon.ico".equals(request.uri())){
System.out.println("图标不处理");
return;
}
Netty高级进阶之基于Netty的HTTP服务器开发
https://hexo.terwer.space/post/http-server-development-based-on-netty.html