概述
在现代 Web 应用中,实时通信功能变得越来越重要。无论是聊天应用、实时通知系统还是协作工具,WebSocket 技术都提供了全双工通信能力。本文将详细介绍如何在 Spring Boot 中集成 WebSocket 服务,构建一个完整的实时通信应用。
项目结构
XML
websocket-learning/
├── src/main/java/com/zgr/websocket/learning/
│ ├── WebsocketLearningApplication.java # 主应用类
│ ├── webscket/
│ │ ├── WebsocketConfig.java # WebSocket 配置
│ │ ├── CustomHandshakeInterceptor.java # 自定义握手拦截器
│ │ └── CustomWebsocketHandler.java # WebSocket 处理器
│ └── controller/
│ └── WebSocketController.java # REST 控制器
└── src/main/resources/
└── application.properties # 应用配置
技术栈
-
Java 17
-
Spring Boot (Spring Boot 4.0.4)
-
Maven 构建工具
-
WebSocket 实时通信协议
Maven 依赖
XML
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
核心代码实现
1. 应用配置
XML
application.properties
server.port=8089
server.servlet.context-path=/api/websocket
spring.application.name=websocket-learning
2.主应用类
java
@SpringBootApplication
public class WebsocketLearningApplication {
public static void main(String[] args) {
SpringApplication.run(WebsocketLearningApplication.class, args);
}
}
3. WebSocket 配置类
WebsocketConfig.java 是整个 WebSocket 服务的核心配置。
java
@Configuration
@EnableWebSocket
public class WebsocketConfig {
@Bean
public WebSocketConfigurer webSocketConfigurer(
HandshakeInterceptor[] handshakeInterceptors,
WebSocketHandler webSocketHandler) {
return registry -> {
registry.addHandler(webSocketHandler, "/ws")
.addInterceptors(handshakeInterceptors)
.setAllowedOrigins("*");
};
}
@Bean
public WebSocketHandler webSocketHandler() {
return new CustomWebsocketHandler();
}
@Bean
public HandshakeInterceptor handshakeInterceptor() {
return new CustomHandshakeInterceptor();
}
}
关键点:
-
@EnableWebSocket:启用 WebSocket 支持
-
注册 WebSocket 端点路径:/ws
-
配置跨域允许:setAllowedOrigins("*")
-
注入自定义处理器和拦截器
4. 自定义握手拦截器
CustomHandshakeInterceptor.java 用于在握手前后执行自定义逻辑。
java
@Slf4j
public class CustomHandshakeInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response,
WebSocketHandler wsHandler,
Map<String, Object> attributes) {
log.info("beforeHandshake");
// 可在此处进行身份验证、参数解析等操作
return true; // 返回 true 允许连接,false 拒绝连接
}
@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response,
WebSocketHandler wsHandler,
@Nullable Exception exception) {
// 握手完成后的处理逻辑
}
}
5. WebSocket 消息处理器
CustomWebsocketHandler.java 继承自 TextWebSocketHandler,处理所有 WebSocket 事件。
java
@Component
@Slf4j
public class CustomWebsocketHandler extends TextWebSocketHandler {
// 存储所有活跃的 WebSocket 会话
private final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) {
String sessionId = session.getId();
sessions.put(sessionId, session);
log.info("WebSocket连接建立成功:{}", sessionId);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
String payload = message.getPayload();
log.info("收到消息:{}", payload);
// 发送回复消息
String replyMessage = "服务器收到消息:" + payload;
session.sendMessage(new TextMessage(replyMessage));
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
String sessionId = session.getId();
sessions.remove(sessionId);
log.info("WebSocket连接关闭:{}", sessionId);
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
log.error("WebSocket传输错误", exception);
}
// 广播消息到所有连接的客户端
public void broadcast(String message) {
for (WebSocketSession session : sessions.values()) {
try {
session.sendMessage(new TextMessage(message));
} catch (IOException e) {
log.error("WebSocket发送消息错误", e);
}
}
}
}
生命周期方法:
-
afterConnectionEstablished:连接建立时调用
-
handleTextMessage:处理客户端发送的文本消息
-
afterConnectionClosed:连接关闭时调用
-
handleTransportError:传输错误时调用
6. REST 控制器
WebSocketController.java 提供 HTTP 接口,用于向所有 WebSocket 客户端广播消息。
java
@RestController
@RequestMapping()
public class WebSocketController {
@Resource
private CustomWebsocketHandler webSocketHandler;
@PostMapping("/broadcast")
public ResponseEntity<String> broadcastMessage(@RequestBody String message) {
webSocketHandler.broadcast(message);
return ResponseEntity.ok("消息广播成功");
}
}
测试应用
启动应用,应用将在 http://localhost:8089/api/websocket 启动,WebSocket 端点位于 ws://localhost:8089***/api/websocket***/ws,连接时,需要主要两个点,这个两个点是我遇到的问题,在这里做一个分享。
1.连接地址,需要加上Spring Boot配置中的server.servlet.context-path地址;
2.如果使用了Spring Security,一定要在配置中允许直接访问websocket的地址,配置的地址就是WebsocketConfig中配置注册WebsocketConfigurer中的paths。
使用Apifo连接Websocket服务并发送http请求广播消息



性能优化建议
-
连接数限制:设置最大连接数,防止资源耗尽
-
心跳机制:定期发送心跳包,检测无效连接
-
消息队列:高并发场景下使用消息队列缓冲
-
集群支持:使用 Redis 或专门的消息中间件支持多实例部署
-
压缩传输:对消息内容进行压缩,减少带宽占用
常见问题解决
1. 跨域问题
// 允许特定域
.setAllowedOrigins("https://example.com")
// 或允许所有域(开发环境)
.setAllowedOrigins("*")
2. 连接超时
// 配置 WebSocket 会话超时时间
session.setMaxIdleTimeout(30000); // 30秒
3. 消息大小限制
// 配置消息缓冲区大小
session.setTextMessageSizeLimit(64 * 1024); // 64KB
总结
通过本文的示例,我们实现了一个完整的 Spring Boot WebSocket 应用,包括:
-
✅ WebSocket 基本配置和端点注册
-
✅ 自定义握手拦截器
-
✅ 完整的消息处理器(连接管理、消息处理、错误处理)
-
✅ REST API 接口进行消息广播
-
✅ 会话管理和消息广播功能
这个示例项目为构建实时通信应用提供了坚实的基础架构,可以根据实际需求进行扩展和优化。无论是构建聊天系统、实时通知服务还是在线协作工具,WebSocket 都是一个强大且高效的选择。
希望这篇博客能帮助你理解 Spring Boot 中 WebSocket 的集成方式。如果有任何问题或建议,欢迎在评论区讨论!