相应模块里面添加3个类
WebSocketConfig,MyWebSocketHandler,WebSocketInterceptor
1.WebSocketConfig
package com.ruoyi.config;
import com.ruoyi.handler.MyWebSocketHandler;
import com.ruoyi.interceptor.WebSocketInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
private static final Logger log = LoggerFactory.getLogger(WebSocketConfig.class);
@Autowired
private MyWebSocketHandler myWebSocketHandler;
@Autowired
private WebSocketInterceptor webSocketInterceptor;
@Value("#{'${websocket.wsHandlers}'.split(',')}")
private String[] paths;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myWebSocketHandler, paths)
.setAllowedOrigins("*")
.addInterceptors(webSocketInterceptor);
}
}
2. MyWebSocketHandler
package com.ruoyi.handler;
import com.ruoyi.common.WebSocketCommon;
import com.ruoyi.common.core.constant.WebSocketConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import java.io.IOException;
@Component
public class MyWebSocketHandler implements WebSocketHandler {
private static final Logger log = LoggerFactory.getLogger(MyWebSocketHandler.class);
@Override
public void afterConnectionEstablished(WebSocketSession session) {
log.info("connect websocket successful!");
Object userId = session.getAttributes().get(WebSocketConstants.TOKEN);
if(userId==null){
return;
}
WebSocketSession oldSession = WebSocketCommon.CLIENT_SESSION.get(WebSocketCommon.getMapKey(session));
if (oldSession != null) {
log.info("close original session-start");
try {
oldSession.close();
} catch (IOException e) {
log.info("close original session failed");
}
}
//新的会话放入
WebSocketCommon.CLIENT_SESSION.put(WebSocketCommon.getMapKey(session),session);
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage> message){
log.info("handle message start");
try {
//String mess = (String) message.getPayload(); //获取客户端发送的消息
//这边可能需要处理更新map里session机制,防止map里面保存的失效,待定,等后面实际运行观察
if(session.isOpen()){
//心跳响应包
session.sendMessage(new PongMessage());
}
} catch (Exception e) {
log.error("e", e);
}
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
log.info("handle message start");
if (session.isOpen()) {
session.close();
}
log.error("connect error", exception);
Object userid = session.getAttributes().get(WebSocketConstants.TOKEN).toString();
if(userid==null){
return;
}
WebSocketCommon.CLIENT_SESSION.remove(WebSocketCommon.getMapKey(session));
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus){
log.error("在线人数: {}" + WebSocketCommon.CLIENT_SESSION.size());
log.error("connection closed: " + closeStatus);
WebSocketCommon.CLIENT_SESSION.remove(WebSocketCommon.getMapKey(session));
log.error("在线人数: {}" + WebSocketCommon.CLIENT_SESSION.size());
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}
3.WebSocketInterceptor
package com.ruoyi.interceptor;
import com.ruoyi.common.core.constant.WebSocketConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import java.util.Map;
@Component
public class WebSocketInterceptor implements HandshakeInterceptor {
private static final Logger log = LoggerFactory.getLogger(WebSocketInterceptor.class);
//在握手之前执行该方法, 继续握手返回true, 中断握手返回false. 通过attributes参数设置WebSocketSession的属性
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes){
if (request instanceof ServletServerHttpRequest) {
String uri = request.getURI().getPath();
String token = uri.substring(uri.lastIndexOf("/")+1);
attributes.put(WebSocketConstants.TOKEN,token);
log.info("current token is:"+token);
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
log.info("coming webSocketInterceptor afterHandshake method...");
}
}
二.nacos中关键配置
在ruoyi-gateway-dev.yml 配置文件中添加如下,我是在ruoyi-collection这个模块中使用websocket的,所以配置路由到这个服务
# websocket模块
- id: ruoyi-websocket
uri: lb:ws://ruoyi-collection
predicates:
- Path=/wsv2/api-docs
- /csrf
- /collection/sendBoxStatus
- /ws
public static ConcurrentHashMap CLIENT_SESSION = new ConcurrentHashMap();
public static String getMapKey(WebSocketSession session){
Object userId = session.getAttributes().get(WebSocketConstants.TOKEN);
if(userId==null){
return null;
}
String useridStr = userId.toString();
return useridStr;
}
}
最后非常感谢这篇文章的作者,参照这篇文章实现了功能,另外有什么问题欢迎留言,一起探讨。
SpringCloud Gateway 集成 WebSocket服务_哦哈哟小朋友的博客-CSDN博客_gateway整合websocket



