Spring整合WebSocket

Spring 整合 websocket 设置

Maven 添加 Jar 包

1
2
3
4
5
6
7
8
9
10
11
12
<!-- spring websocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- websocket end -->

Spring xml 配置方式

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- websocket 配置 -->
<websocket:message-broker application-destination-prefix="/app">
<websocket:stomp-endpoint path="/websocket">
<websocket:sockjs />
</websocket:stomp-endpoint>
<websocket:simple-broker prefix="/topic"/>
<websocket:client-inbound-channel>
<websocket:interceptors>
<bean class="net.example.projects.web.WebSocketInterceptor"/>
</websocket:interceptors>
</websocket:client-inbound-channel>
</websocket:message-broker>
<!-- websocket end -->

此处启用 stomp

STOMP 中文为: 面向消息的简单文本协议

websocket定义了两种传输信息类型:文本信息和二进制信息。类型虽然被确定,但是他们的传输体是没有规定的。所以,需要用一种简单的文本传输类型来规定传输内容,它可以作为通讯中的文本传输协议。

STOMP 是基于帧的协议,客户端和服务器使用 STOMP 帧流通讯

一个 STOMP 客户端是一个可以以两种模式运行的用户代理,可能是同时运行两种模式。

  • 作为生产者,通过SEND框架将消息发送给服务器的某个服务
  • 作为消费者,通过SUBSCRIBE制定一个目标服务,通过MESSAGE框架,从服务器接收消息。

基于 websocket 的一层 STOMP 封装,让业务端只需关心数据本身,不需要太过关心文本协议。当然还是需要了解一些 STOMP 协议各个 Frame 的概念和应用场景。

拦截器配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class WebSocketInterceptor extends ChannelInterceptorAdapter {

@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
//1、判断是否首次连接
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
String userId = accessor.getNativeHeader("userId").get(0);
String name = userId;
Principal principal = () -> name;
WebSocketManager.connect(name);
accessor.setUser(principal);
return message;
} else if (StompCommand.DISCONNECT.equals(accessor.getCommand())) {
Principal principal = accessor.getUser();
WebSocketManager.disconnect(principal.getName());
} else {

}
return message;
}
}

拦截处理连接和断开操作,Principal 设置连接的用户,之后就可以发送消息到指定用户。

常用 Command

  • CONNECT
  • CONNECTED
  • SEND
  • SUBSRIBE
  • UNSUBSRIBE
  • BEGIN
  • COMMIT
  • ABORT
  • ACK
  • NACK
  • DISCONNECT

消息

服务器可以通过@MessageMapping方法处理请求

SendToUser("/topic/websocket")发送消息

需要强调的是 web.xml 中的路径匹配问题 写为/全部匹配的

如果使用路径匹配/wsk/*

spring 中的地址不能写为<websocket:mapping path=”/wsk/echo” 只需要写为 <websocket:mapping path=”/echo”就可以了,不然无法访问,这个是很多人都会遇到的坑.需特别注意

手动管理 WebSocketSession

配置时添加

1
2
3
4
5
<websocket:transport>
<websocket:decorator-factories>
<bean class="net.example.web.CustomWebSocketHandlerDecorator"/>
</websocket:decorator-factories>
</websocket:transport>

添加代码

carbon

将 WebSocketSession 保存,留作后续处理