1.引入pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.websocket配置类
/**
* websocket配置
* @Date: 2020-08-22
*/
@Configuration
/**
* @EnableWebSocketMessageBroker
* 开启使用 STOMP 协议来传输基于代理的消息,Broker是代理
*/
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry)
{
/**
* //注册一个STOMP的endpoint,并指定使用SockJS协议
* setErrorHandler: 设置一个错误处理的 Handler, 以便捕捉错误信息
* addEndpoint: 切入点, 客户端在 new SockJs 的时候用到
* setAllowedOrigins:设置为「*」表示接收 http 和 https 的请求
* withSockJS: 使用 SockJS
*/
registry.setErrorHandler(this.webSocketHandler())
.addEndpoint("/endpointNiu") //websocket连接入口
.setAllowedOrigins("*") //解决跨域问题
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry)
{
/**
* 参数是多个 destinationPrefixes, 服务端发送消息的 destination 要有这些前缀 广播式应配置一个/aiKnowledge
*/
registry.enableSimpleBroker("/broadcast","/user");
/**
* 设置点对点时, destination 的前缀, 如客户端订阅 点对点使用的订阅前缀(客户端订阅路径上会体现出来),不设置的话,默认也是/user/
*/
registry.setUserDestinationPrefix("/user");
}
/**
* WebSocket Error 处理
*
* @return WebSocket Error 处理器
*/
@Bean
public StompSubProtocolErrorHandler webSocketHandler() {
return new WebSocketErrorHandler();
}
/**
* ServerEndpointExporter 作用
*
* 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint
*
* @return
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
3.连接websocket监听类
@Component
public class WebSocketConnectListener implements ApplicationListener<SessionConnectEvent> {
@Override
public void onApplicationEvent(SessionConnectEvent sessionConnectEvent) {
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(sessionConnectEvent.getMessage());
String sessionId = accessor.getSessionId();
SessionUtils.addSession(sessionId);
System.out.println("sessionId: {} 已连接"+ sessionId);
}
}
4.断开websocket监听类
@Component
public class WebSocketDisconnectListener implements ApplicationListener<SessionDisconnectEvent> {
@Override
public void onApplicationEvent(SessionDisconnectEvent event) {
StompHeaderAccessor sha = StompHeaderAccessor.wrap(event.getMessage());
String sessionId = sha.getSessionId();
SessionUtils.removeSession(sessionId);
System.out.println("sessionId: {} 已断开"+ sessionId);
}
}
5.错误处理类
public class WebSocketErrorHandler extends StompSubProtocolErrorHandler {
public WebSocketErrorHandler()
{
super();
}
@Override
public Message<byte[]> handleClientMessageProcessingError(Message<byte[]> clientMessage, Throwable ex) {
return super.handleClientMessageProcessingError(clientMessage, ex);
}
@Override
public Message<byte[]> handleErrorMessageToClient(Message<byte[]> errorMessage) {
return super.handleErrorMessageToClient(errorMessage);
}
@Override
protected Message<byte[]> handleInternal(StompHeaderAccessor errorHeaderAccessor, byte[] errorPayload, Throwable cause, StompHeaderAccessor clientHeaderAccessor) {
return super.handleInternal(errorHeaderAccessor, errorPayload, cause, clientHeaderAccessor);
}
}
6.对外调用接口实现类 (业务问题这里只需实现点对点模式发送消息)
@Service
public class WebSocketServiceImpl implements WebSocketService {
@Autowired
private HandleMessage handleMessage;
@Autowired
private SimpMessagingTemplate messagingTemplate;
/**
* 给某个用户主动推送消息 (点对点推送消息)
* @param userName 推送消息的用户名
* */
@Override
public void sendMessageStatus(String userName) {
UserBean user = UserHolder.getUser();
Boolean off = handleMessage.getMessageByUser(user.getId());
messagingTemplate.convertAndSendToUser(userName, "/aiKnowledge/pointMessage", off);
}
}
7.前端vue代码块
//websocket method
initWebSocket() {
this.connection();
let self = this;
// 断开重连机制,尝试发送消息,捕获异常发生时重连
this.timer = setInterval(() => {
try {
self.stompClient.send("test");
} catch (err) {
console.log("断线了: " + err);
self.connection();
}
}, 60000);
},
connection() {
// 建立连接对象
this.socket = new SockJS('http://localhost:9091/endpointNiu');//连接服务端提供的通信接口,连接以后才可以订阅广播消息和个人消息
// 获取STOMP子协议的客户端对象
this.stompClient = Stomp.over(this.socket);
//获取token
const token = getToken();
// 定义客户端的认证信息,按需求配置 param
var headers = {
token: token,
};
// 向服务器发起websocket连接
if(this.user != null){
const userEmail = this.user.username;
this.stompClient.connect(headers,(frame) => {
this.stompClient.subscribe('/user/'+userEmail+'/aiKnowledge/pointMessage', (msgStatus) => { // 订阅服务端提供的某个topic
// msg存放的是服务端发送给我们的信息
if(msgStatus.body == "false"){
this.hasMessageNoRead = false ;
}else{
this.hasMessageNoRead = true ;
}
});
}, (err) => {
// 连接发生错误时的处理函数
console.log(err);
});
}
},
// 断开连接
disconnect() {
if (this.stompClient != null) {
this.stompClient.disconnect();
}
}
}
调用方式:在vue 的methods属性中加入方法,使用initWebSocket()方法连接websocket,一般是在computed中调用this.initWebSocket()。
作者前端很烂,vue半问半写出来的,如果不对的地方,忍着, 请查阅其他博客资料