一、Maven依赖引入
1. Netty-WebSocket-Spring-Boot-Starter
/* by 01130.hk - online tools website : 01130.hk/zh/huoxingwen.html */ <dependency> <groupId>org.yeauty</groupId> <artifactId>netty-websocket-spring-boot-starter</artifactId> <version>0.13.0</version> <!-- 请使用最新版本 --> </dependency>2. Spring官方WebSocket Starter
/* by 01130.hk - online tools website : 01130.hk/zh/huoxingwen.html */ <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>二、核心差异对比
| 特性 | Netty-WebSocket | Spring官方Starter |
|---|---|---|
| 底层框架 | Netty NIO框架 (非阻塞IO) | Servlet容器 (Tomcat/Jetty) |
| 协议支持 | 原生WebSocket + 自定义二进制协议 | WebSocket + STOMP消息协议 |
| 线程模型 | Reactor多线程模型 (Boss/Worker) | Servlet线程池模型 |
| 容器依赖 | 无 (可独立运行) | 必须依赖Servlet容器 |
| 编程范式 | 事件驱动模型 (类似Netty Handler) | 消息代理模型 (发布/订阅) |
| 与Spring集成 | 中等 (需手动管理会话) | 深度集成 (自动配置+安全支持) |
| 学习曲线 | 较陡峭 (需理解Netty概念) | 平缓 (Spring开发者友好) |
| 适用场景 | 高频实时数据/自定义协议 | 企业消息系统/标准文本通信 |
三、使用场景决策指南
✅ 选择 Netty-WebSocket 当:
- 需要处理高频实时数据:金融行情推送、物联网传感器数据
- 使用自定义二进制协议:游戏数据包、音视频流传输
- 追求极致性能:要求1万+并发连接,低延迟响应
- 脱离Servlet容器:希望WebSocket服务独立部署
✅ 选择 Spring官方Starter 当:
- 开发企业级消息系统:聊天应用、实时通知系统
- 需要完整STOMP支持:利用消息代理和订阅机制
- 快速集成Spring生态:与Security、Data等组件协作
- 兼容旧浏览器:需要SockJS回退支持
四、核心代码实现对比
方案1:Netty-WebSocket实现(实时数据推送)
@SpringBootApplication @EnableNettyWebSocket // 启用Netty WebSocket服务器 public class DataPushApplication { public static void main(String[] args) { SpringApplication.run(DataPushApplication.class, args); } } /** * 实时数据推送处理器 * 特点:直接操作Session,手动管理连接 */ @ServerEndpoint(host = "0.0.0.0", port = "8080", path = "/realtime") public class DataPushHandler { // 存储所有活动会话 private static final Set<Session> sessions = ConcurrentHashMap.newKeySet(); @OnOpen public void onOpen(Session session) { sessions.add(session); session.sendText("CONNECTED|" + LocalTime.now()); } @OnText public void onText(Session session, String message) { // 处理文本消息(如控制指令) String response = processCommand(message); session.sendText(response); } @OnBinary public void onBinary(Session session, byte[] bytes) { // 解析二进制数据(如传感器数据) SensorData data = SensorDecoder.decode(bytes); // 处理数据逻辑... byte[] response = SensorEncoder.encode(data); session.sendBinary(response); } @OnClose public void onClose(Session session, CloseReason reason) { sessions.remove(session); } // 广播数据给所有客户端 public static void broadcast(byte[] data) { sessions.forEach(session -> { if (session.isOpen()) { session.sendBinary(data); } }); } }方案2:Spring官方Starter实现(完整聊天室)
/** * WebSocket配置类 * 特点:使用STOMP协议,配置消息代理 */ @Configuration @EnableWebSocketMessageBroker public class ChatConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { // 客户端连接端点 registry.addEndpoint("/chat-ws") .setAllowedOriginPatterns("*") .withSockJS(); // 浏览器兼容支持 } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { // 启用内存消息代理 registry.enableSimpleBroker("/topic", "/queue"); // 设置应用消息前缀 registry.setApplicationDestinationPrefixes("/app"); // 设置用户私有队列前缀 registry.setUserDestinationPrefix("/user"); } } /** * 聊天控制器 * 特点:使用高级消息抽象,自动处理订阅 */ @Controller public class ChatController { @Autowired private SimpMessagingTemplate messagingTemplate; // 处理公共聊天消息 @MessageMapping("/chat") @SendTo("/topic/messages") public ChatMessage handlePublicMessage(@Payload ChatMessage message, Principal principal) { message.setSender(principal.getName()); message.setTimestamp(LocalDateTime.now()); return message; } // 处理私有消息 @MessageMapping("/private") public void handlePrivateMessage(@Payload ChatMessage message, Principal principal) { message.setSender(principal.getName()); message.setTimestamp(LocalDateTime.now()); // 定向发送给接收者 messagingTemplate.convertAndSendToUser( message.getRecipient(), "/queue/private", message ); } // 用户上线处理 @EventListener public void handleConnect(SessionConnectedEvent event) { String username = event.getUser().getName(); // 通知所有用户更新在线列表 messagingTemplate.convertAndSend("/topic/onlineUsers", userService.getOnlineUsers()); } } /** * 消息实体类 */ public class ChatMessage { private String sender; // 发送者 private String recipient; // 接收者(私聊使用) private String content; // 消息内容 private LocalDateTime timestamp; // 时间戳 // getters & setters }五、关键差异解析
连接管理方式
- Netty:手动维护
Session集合,直接操作连接 - Spring:自动管理连接,通过
SimpMessagingTemplate发送消息
- Netty:手动维护
消息处理模式
graph LR A[客户端] --> B{Netty方案} B --> C[直接处理二进制数据] B --> D[自定义协议解析] A --> E{Spring方案} E --> F[STOMP消息代理] E --> G[发布/订阅模式]异常处理机制
- Netty:通过
@OnError捕获异常,需手动关闭问题会话 - Spring:全局异常处理器
@MessageExceptionHandler统一处理
- Netty:通过
集群支持
- Netty:需自行实现分布式会话管理(如Redis)
- Spring:天然支持通过消息代理(RabbitMQ/Redis)实现集群
六、选型建议总结
| 项目特征 | 推荐方案 | 理由说明 |
|---|---|---|
| 高频实时数据(>1000 TPS) | Netty-WebSocket | 低延迟、高吞吐量 |
| 企业级聊天系统 | Spring官方Starter | STOMP协议支持完善 |
| 自定义二进制协议 | Netty-WebSocket | 直接操作字节数据 |
| 需要SockJS兼容旧浏览器 | Spring官方Starter | 内置SockJS支持 |
| 微服务架构中的独立服务 | Netty-WebSocket | 不依赖Servlet容器 |
| 需要深度整合Spring Security | Spring官方Starter | 原生支持安全拦截 |
黄金实践法则:
新项目若不需要处理二进制协议,优先选择Spring官方方案;
现有系统需添加高性能实时通道,引入Netty作为独立服务模块;
关键业务系统建议同时实现两种方案,Netty处理实时数据流,Spring处理业务消息。