⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 juejin.cn/post/7521721402527301641 「一旅人」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

一、Maven依赖引入

1. Netty-WebSocket-Spring-Boot-Starter

<dependency>
<groupId>org.yeauty</groupId>
<artifactId>netty-websocket-spring-boot-starter</artifactId>
<version>0.13.0</version> <!-- 请使用最新版本 -->
</dependency>

2. Spring官方WebSocket Starter

<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服务器
publicclass DataPushApplication {
public static void main(String[] args) {
SpringApplication.run(DataPushApplication.class, args);
}
}

/**
* 实时数据推送处理器
* 特点:直接操作Session,手动管理连接
*/
@ServerEndpoint(host = "0.0.0.0", port = "8080", path = "/realtime")
publicclass DataPushHandler {

// 存储所有活动会话
privatestaticfinal 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
publicclass 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
publicclass 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());
}
}

/**
* 消息实体类
*/
publicclass ChatMessage {
private String sender; // 发送者
private String recipient; // 接收者(私聊使用)
private String content; // 消息内容
private LocalDateTime timestamp; // 时间戳

// getters & setters
}

五、关键差异解析

1.连接管理方式

  • Netty: 手动维护Session集合,直接操作连接
  • Spring: 自动管理连接,通过SimpMessagingTemplate发送消息

2.消息处理模式

3.异常处理机制

  • Netty: 通过@OnError捕获异常,需手动关闭问题会话
  • Spring: 全局异常处理器@MessageExceptionHandler统一处理

4.集群支持

  • 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处理业务消息。

通过以上对比,开发者可根据实际场景需求选择最合适的WebSocket实现方案。两种方案各有优势,理解其核心差异是做出正确技术决策的关键。

文章目录
  1. 1. 一、Maven依赖引入
    1. 1.0.1. 1. Netty-WebSocket-Spring-Boot-Starter
    2. 1.0.2. 2. Spring官方WebSocket Starter
  • 2. 二、核心差异对比
  • 3. 三、使用场景决策指南
    1. 3.0.1. ✅ 选择 Netty-WebSocket 当:
    2. 3.0.2. ✅ 选择 Spring官方Starter 当:
  • 4. 四、核心代码实现对比
    1. 4.0.1. 方案1:Netty-WebSocket实现(实时数据推送)
    2. 4.0.2. 方案2:Spring官方Starter实现(完整聊天室)
  • 5. 五、关键差异解析
    1. 5.0.1. 1.连接管理方式
    2. 5.0.2. 2.消息处理模式
    3. 5.0.3. 3.异常处理机制
    4. 5.0.4. 4.集群支持
  • 6. 六、选型建议总结
    1. 6.0.1. 黄金实践法则: