springboot 中使用 websocket
第一步:开启websocket
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {// 其他 WebSocket 处理器的注册(可选)}// 关键:注册 @ServerEndpoint 注解的类@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
第二步:编写具体的处理逻辑
@ServerEndpoint("/anno/myMsg/{tenantId}/{principal}") //前端请求 这个地址,即可建立 websocket 链接
@Component
@Slf4j
public class TestEndpoint {@OnOpenpublic void onOpen(Session session) { //连接建立之后,做什么log.info("连接成功");WebSocketObserver observer = new WebSocketObserver(session);// get subjectWebSocketSubject subject = WebSocketSubject.Holder.getSubject(session.getId());// register observer into subjectsubject.addObserver(observer);}@OnClose //链接关闭的时候,做什么public void onClose(Session session) { log.info("连接关闭");// get subjectWebSocketSubject subject = WebSocketSubject.Holder.getSubject(session.getId());// get observerWebSocketObserver observer = new WebSocketObserver(session);// delete observer from subjectsubject.deleteObserver(observer);// close session and close Web Socket connectiontry {if (session.isOpen()) {session.close();}} catch (IOException e) {throw new RuntimeException("close web socket session error.", e);}}@OnMessage //接收到消息之后,怎么处理public String onMsg(@PathParam("principal") String principal, String text) {if (StrUtil.isEmpty(text)) {return "";}return "server 收到消息:" + text;}@OnError //出现异常的时候,怎么处理public void onError(Session session, Throwable error) {log.info("连接error");throw new RuntimeException("web socket error.", error);}
}
就这两步即可在springboot中使用 websocket 。由于springboot 集成的 websocket 非常简洁,避免了去关心底层的 通道/套接字 等一系列东西,只需要关心业务即可
对websocket的加深理解
当前端想建立 websocket 请求的时候 会发送类似 ws://your-domain.com/anno/myMsg/1234/userAlice 这样的一个链接,那么这个链接就是一个单纯的 websocket 请求么?
Websocket 请求的本质
WebSocket 请求的链接(如 ws://your-domain.com/anno/myMsg/1234/userAlice
)并非单纯的独立连接。WebSocket 协议在建立时需通过 HTTP 或 HTTPS 完成初始握手,之后才升级为双向通信的 WebSocket 连接。因此,WebSocket 与 HTTP 存在明确的关联性。
WebSocket 与 HTTP 的联系
WebSocket 连接的建立依赖 HTTP 的升级机制。客户端发送一个包含 Upgrade: websocket
和 Connection: Upgrade
头部的 HTTP 请求,服务器响应状态码 101 Switching Protocols
后,协议升级为 WebSocket。此过程称为“握手”。
示例握手请求:
GET /anno/myMsg/1234/userAlice HTTP/1.1
Host: your-domain.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
示例握手响应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
WebSocket 链接的路径含义
路径 /anno/myMsg/1234/userAlice
通常由后端路由解析,用于标识通信频道或用户身份。例如:
/anno
可能表示通知服务模块。myMsg/1234
可能标识特定消息或会话。userAlice
可能用于区分客户端。
WebSocket 与 HTTP 的区别
通信模式
- HTTP:无状态,单向(客户端请求-服务器响应)。
- WebSocket:全双工,持久化连接,服务器可主动推送数据。
协议标识
- HTTP 使用
http://
或https://
。 - WebSocket 使用
ws://
(明文)或wss://
(加密)。
性能对比
WebSocket 避免了 HTTP 的重复握手开销,适合实时应用(如聊天、游戏)。
实际应用中的关联案例
-
负载均衡
WebSocket 连接可能经过 HTTP 反向代理(如 Nginx),需配置proxy_set_header Upgrade $http_upgrade
等参数。 -
安全限制
同源策略和 CORS 规则可能影响 WebSocket 连接,需处理与 HTTP 相同的安全策略。 -
身份验证
初始握手阶段可通过 HTTP 头部(如Authorization
)传递身份令牌,与 REST API 共享鉴权逻辑。
总结
WebSocket 链接并非独立于 HTTP,其建立依赖于 HTTP 升级机制。路径设计由后端路由控制,用于业务逻辑区分。两者在协议层存在明确关联,但通信模式与性能特点截然不同。
全双工 半双工 单工
全双工
全双工通信允许双方同时发送和接收信息,就像日常打电话。通话时双方可以同时说话和听对方说话,无需等待对方结束。现代网络通信如视频通话也采用全双工模式,数据双向实时传输。
半双工
半双工通信中,双方可以互相发送信息,但不能同时进行。类似对讲机使用场景:按下通话键时只能说话,松开才能听对方回复。传统网络集线器(HUB)也属于半双工,同一时间只允许单向数据传输。
单工
单工通信仅允许单向信息传输,如广播、电视信号。听众只能接收内容,无法通过广播频道反向发送信息。键盘向电脑输入数据也是单工例子,信号仅从键盘流向主机。