Spring Boot 整合 Netty-Boot
本指南将演示如何在 Spring Boot 应用程序中集成 Netty-Boot,使您能够在 Spring Boot 的上下文中使用 Netty 来处理 HTTP 和 WebSocket 请求。
前提条件
- JDK 版本:8 或更高
- 构建工具:Maven 或 Gradle
- 知识准备:具备 Spring Boot 和 Netty 的基本知识
步骤一:配置 Netty 服务器端口
首先,在 app.properties
配置文件中指定 Netty 服务器运行的端口。
netty.server.port=8869
这将设置 Netty 服务器监听在 8869
端口上。
步骤二:创建 HTTP 处理器
创建一个名为 OkHandler
的处理器类,用于管理 HTTP 请求。
package com.litongjava.study.netty.boot.handler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class WsHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {
if (frame instanceof TextWebSocketFrame) {
String requestText = ((TextWebSocketFrame) frame).text();
// 返回相同的消息
ctx.channel().writeAndFlush(new TextWebSocketFrame("Server received: " + requestText));
} else if (frame instanceof BinaryWebSocketFrame) {
} else if (frame instanceof CloseWebSocketFrame) {
ctx.channel().close();
} else if (frame instanceof PingWebSocketFrame) {
ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content().retain()));
} else {
throw new UnsupportedOperationException("不支持的帧类型: " + frame.getClass().getName());
}
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
log.info("ctx:{}", ctx);
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
log.info("ctx:{}", ctx);
}
}
说明:
- 处理不同类型的 WebSocket 帧:
TextWebSocketFrame
:将文本消息回传给客户端。CloseWebSocketFrame
:关闭连接。PingWebSocketFrame
:响应一个PongWebSocketFrame
。
步骤四:配置 Netty-Boot 服务器
创建一个名为 NettyBootConfig
的配置类,设置 Netty 服务器和处理器。
package com.netty;
import com.litongjava.context.BootConfiguration;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.netty.boot.http.HttpRequestRouter;
import com.litongjava.netty.boot.listener.ChannelConnectionListener;
import com.litongjava.netty.boot.server.NettyBootServer;
import com.litongjava.netty.boot.websocket.WebsocketRouter;
import com.netty.handler.ChatHandler;
import com.netty.handler.OkHandler;
import com.netty.handler.WsHandler;
import com.netty.listener.MyChannelConnectionListener;
public class NettyBootConfig implements BootConfiguration {
@Override
public void config() {
NettyBootServer nettyBootServer = NettyBootServer.me();
// 创建并设置自定义的 ChannelConnectionListener
ChannelConnectionListener myChannelConnectionListener = new MyChannelConnectionListener();
nettyBootServer.setChannelConnectionListener(myChannelConnectionListener);
// 设置 HTTP 路由
HttpRequestRouter httpRouter = nettyBootServer.getHttpRequestRouter();
OkHandler okHandler = Aop.get(OkHandler.class);
httpRouter.add("/txt", okHandler::txt);
httpRouter.add("/json", okHandler::json);
httpRouter.add("/echo", okHandler::echo);
// 设置 WebSocket 路由
WebsocketRouter websocketRouter = nettyBootServer.getWebsocketRouter();
Supplier<SimpleChannelInboundHandler<WebSocketFrame>> wsHandlerSupplier = WsHandler::new;
websocketRouter.add("/ws", wsHandlerSupplier);
}
}
说明:
- 实现
BootConfiguration
接口来配置 Netty 服务器。 - 设置自定义的
ChannelConnectionListener
来管理连接事件。 - 使用
HttpRequestRouter
配置 HTTP 路由,将 URL 映射到处理方法。 - 使用
WebsocketRouter
配置 WebSocket 路由。
步骤五:将 Netty-Boot 集成到 Spring Boot 中
创建一个名为 NettyServerConfig
的 Spring Boot 配置类,将 Netty 服务器运行在 Spring 上下文中。
package com.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.litongjava.context.Context;
import com.litongjava.netty.boot.NettyApplication;
import com.netty.NettyBootConfig;
@Configuration
public class NettyServerConfig {
@Bean(destroyMethod = "close")
public Context nettyContext() {
NettyBootConfig bootConfig = new NettyBootConfig();
return NettyApplication.run(NettyServerConfig.class, bootConfig, new String[] {});
}
}
说明:
- 使用
@Configuration
注解,表示这是一个 Spring 配置类。 - 定义了一个名为
nettyContext
的 Bean,使用NettyApplication.run
方法来初始化和运行 Netty 服务器。 - 设置
destroyMethod = "close"
,确保在应用程序上下文关闭时,Netty 服务器能够正确关闭。
步骤六:启动应用程序并进行测试
所有配置就绪后,以正常方式启动您的 Spring Boot 应用程序。Netty 服务器将被初始化,并开始监听指定的端口(8869
)。
测试 HTTP 端点
纯文本响应
发送 GET 请求到
http://localhost:8869/txt
:curl http://localhost:8869/txt
响应:
Hello, this is the HTTP response!
JSON 响应
发送 GET 请求到
http://localhost:8869/json
:curl http://localhost:8869/json
响应:
{ "status": "ok", "message": "Success" }
Echo 端点
发送 POST 请求到
http://localhost:8869/echo
,并附带数据:curl -X POST http://localhost:8869/echo -d "测试数据"
响应:
[包含 "测试数据" 的完整 HTTP 请求详情]
测试 WebSocket 端点
使用 WebSocket 客户端连接到 ws://localhost:8869/ws
。
发送文本消息,例如 "Hello WebSocket"。
服务器将响应:
Server received: Hello WebSocket
结论
您已经成功地将 Netty-Boot 集成到了 Spring Boot 应用程序中,能够处理 HTTP 和 WebSocket 请求。通过这种设置,您可以在熟悉的 Spring Boot 环境中利用 Netty 的高性能网络能力。
附加说明
- 依赖注入:处理器通过
Aop.get(Class)
方法获取,意味着使用了 AOP 框架进行依赖注入。请确保您的应用程序中已正确配置 AOP(面向切面编程)。 - ChannelConnectionListener:自定义实现的
ChannelConnectionListener
允许您管理与通道连接相关的事件,例如通道何时激活或不活跃。 - 线程安全:如果处理器维护状态,请确保它们是线程安全的,因为 Netty 可能会并发处理多个请求。