-
技术栈
前端
h5 vue sockjs stomp axios
后端
SpringBoot websocket
-
功能
1. 服务端主动推送消息
2. 断开后重连机制
-
实现
不解释直接上代码,可以关注下面的相关技术群和公众号
pom文件里面引用
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> <version>2.3.3.RELEASE</version></dependency>
@Configuration@EnableWebSocketMessageBrokerpublic class WebSocketConfig implements WebSocketMessageBrokerConfigurer{ @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.setErrorHandler(this.webSocketHandler()) .addEndpoint("/api/h5/endpointstore") .setAllowedOrigins("*") .withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/topic", "/queue"); registry.setUserDestinationPrefix("/user"); } @Bean public StompSubProtocolErrorHandler webSocketHandler() { return new WebSocketErrorHandler (); }}
@Componentpublic class WebSocketConnectListener implements ApplicationListener<SessionConnectEvent>{ private Logger logger = LoggerFactory.getLogger(WebSocketConnectListener.class); @Override public void onApplicationEvent(SessionConnectEvent sessionConnectEvent) { StompHeaderAccessor accessor = StompHeaderAccessor.wrap(sessionConnectEvent.getMessage()); String sessionId = accessor.getSessionId(); logger.info("sessionId: {} 已连接", sessionId); }}
@Componentpublic class WebSocketDisconnectListener implements ApplicationListener<SessionDisconnectEvent>{ private Logger logger = LoggerFactory.getLogger(WebSocketDisconnectListener.class); @Override public void onApplicationEvent(SessionDisconnectEvent event) { StompHeaderAccessor sha = StompHeaderAccessor.wrap(event.getMessage()); String sessionId = sha.getSessionId(); logger.info("sessionId: {} 已断开", sessionId); }}
public class WebSocketErrorHandler extends StompSubProtocolErrorHandler { private Logger logger = LoggerFactory.getLogger(WebSocketErrorHandler.class); public WebSocketErrorHandler() { super(); } @Override public Message<byte[]> handleClientMessageProcessingError(Message<byte[]> clientMessage, Throwable ex) { logger.error("handleClientMessageProcessingError:clientMessage-" + clientMessage + ", error-" + ex.getMessage()); return super.handleClientMessageProcessingError(clientMessage, ex); } @Override public Message<byte[]> handleErrorMessageToClient(Message<byte[]> errorMessage) { logger.error("handleErrorMessageToClient:errorMessage-" + errorMessage); return super.handleErrorMessageToClient(errorMessage); } @Override protected Message<byte[]> handleInternal(StompHeaderAccessor errorHeaderAccessor, byte[] errorPayload, Throwable cause, StompHeaderAccessor clientHeaderAccessor) { logger.error("handleInternal:errorHeaderAccessor-" + errorHeaderAccessor + ", errorPayload-" + errorPayload + ", error-" + cause.getMessage() + ", clientHeaderAccessor-" + clientHeaderAccessor); return super.handleInternal(errorHeaderAccessor, errorPayload, cause, clientHeaderAccessor); }
@RestControllerpublic class MessageController { Logger logger = LoggerFactory.getLogger(MessageController.class); @Autowired private SimpMessagingTemplate messagingTemplate; @RequestMapping("/api/h5/sendMsgBro") @ResponseBody public void sendMsg() { logger.debug("服务器主动推送的广播消息"); messagingTemplate.convertAndSend("/topic/reloadpic", "服务器主动推送的广播消息"); }}
mounted: function () {
this.initWebSocket()
},
methods: {
initWebSocket: function () {
this.connection()
// 需要有一个失败重连得到问题
},
connection: function (count) {
let num=count||1;
const socket = new SockJS(`${base_url}/h5/endpointstore`)
this.stompClient = Stomp.over(socket)
//建立连接,订阅主题
this.stompClient.connect({}, (frame) => {
this.stompClient.subscribe('/topic/reloadpic', (val) => {
alert("重新加载图片")
window.location.reload(true);
})
},()=>
{
if (num < 10) {
console.log("重试链接次数:"+num);
setTimeout(() => {
this.connection(num + 1);
}, 10000 * num);
} else {
console.log("重试"+num+"此放弃重连了");
}
})
}}