mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 20:28:44 +08:00 
			
		
		
		
	feat: websocket init
This commit is contained in:
		@@ -0,0 +1,14 @@
 | 
			
		||||
package cn.iocoder.yudao.framework.websocket.config;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.websocket.core.UserHandshakeInterceptor;
 | 
			
		||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.web.socket.server.HandshakeInterceptor;
 | 
			
		||||
 | 
			
		||||
@EnableConfigurationProperties(WebSocketProperties.class)
 | 
			
		||||
public class WebSocketHandlerConfig {
 | 
			
		||||
    @Bean
 | 
			
		||||
    public HandshakeInterceptor handshakeInterceptor() {
 | 
			
		||||
        return new UserHandshakeInterceptor();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,29 @@
 | 
			
		||||
package cn.iocoder.yudao.framework.websocket.config;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.springframework.boot.context.properties.ConfigurationProperties;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * WebSocket 配置项
 | 
			
		||||
 *
 | 
			
		||||
 * @author xingyu4j
 | 
			
		||||
 */
 | 
			
		||||
@ConfigurationProperties("yudao.websocket")
 | 
			
		||||
@Data
 | 
			
		||||
@Validated
 | 
			
		||||
public class WebSocketProperties {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 路径
 | 
			
		||||
     */
 | 
			
		||||
    private String path = "";
 | 
			
		||||
    /**
 | 
			
		||||
     * 默认最多允许同时在线用户数
 | 
			
		||||
     */
 | 
			
		||||
    private int maxOnlineCount = 0;
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否保存session
 | 
			
		||||
     */
 | 
			
		||||
    private boolean sessionMap = true;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,34 @@
 | 
			
		||||
package cn.iocoder.yudao.framework.websocket.config;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
 | 
			
		||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 | 
			
		||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 | 
			
		||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.web.socket.WebSocketHandler;
 | 
			
		||||
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
 | 
			
		||||
import org.springframework.web.socket.server.HandshakeInterceptor;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * WebSocket 自动配置
 | 
			
		||||
 *
 | 
			
		||||
 * @author xingyu4j
 | 
			
		||||
 */
 | 
			
		||||
@AutoConfiguration
 | 
			
		||||
// 允许使用 yudao.websocket.enable=false 禁用websocket
 | 
			
		||||
@ConditionalOnProperty(prefix = "yudao.websocket", value = "enable", matchIfMissing = true)
 | 
			
		||||
@EnableConfigurationProperties(WebSocketProperties.class)
 | 
			
		||||
public class YudaoWebSocketAutoConfiguration {
 | 
			
		||||
    @Bean
 | 
			
		||||
    @ConditionalOnMissingBean
 | 
			
		||||
    public WebSocketConfigurer webSocketConfigurer(List<HandshakeInterceptor> handshakeInterceptor,
 | 
			
		||||
                                                   WebSocketHandler webSocketHandler,
 | 
			
		||||
                                                   WebSocketProperties webSocketProperties) {
 | 
			
		||||
 | 
			
		||||
        return registry -> registry
 | 
			
		||||
                .addHandler(webSocketHandler, webSocketProperties.getPath())
 | 
			
		||||
                .addInterceptors(handshakeInterceptor.toArray(new HandshakeInterceptor[0]));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,24 @@
 | 
			
		||||
package cn.iocoder.yudao.framework.websocket.core;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
 | 
			
		||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 | 
			
		||||
import org.springframework.http.server.ServerHttpRequest;
 | 
			
		||||
import org.springframework.http.server.ServerHttpResponse;
 | 
			
		||||
import org.springframework.web.socket.WebSocketHandler;
 | 
			
		||||
import org.springframework.web.socket.server.HandshakeInterceptor;
 | 
			
		||||
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
public class UserHandshakeInterceptor implements HandshakeInterceptor {
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
 | 
			
		||||
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
 | 
			
		||||
        attributes.put(WebSocketKeyDefine.LOGIN_USER, loginUser);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
package cn.iocoder.yudao.framework.websocket.core;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class WebSocketKeyDefine {
 | 
			
		||||
    public static final String LOGIN_USER ="LOGIN_USER";
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,24 @@
 | 
			
		||||
package cn.iocoder.yudao.framework.websocket.core;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
public class WebSocketMessageDO {
 | 
			
		||||
    /**
 | 
			
		||||
     * 接收消息的seesion
 | 
			
		||||
     */
 | 
			
		||||
    private List<Object> seesionKeyList;
 | 
			
		||||
    /**
 | 
			
		||||
     * 发送消息
 | 
			
		||||
     */
 | 
			
		||||
    private String msgText;
 | 
			
		||||
 | 
			
		||||
    public static WebSocketMessageDO build(List<Object> seesionKeyList, String msgText) {
 | 
			
		||||
        return new WebSocketMessageDO().setMsgText(msgText).setSeesionKeyList(seesionKeyList);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,36 @@
 | 
			
		||||
package cn.iocoder.yudao.framework.websocket.core;
 | 
			
		||||
 | 
			
		||||
import org.springframework.web.socket.WebSocketSession;
 | 
			
		||||
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.concurrent.ConcurrentHashMap;
 | 
			
		||||
 | 
			
		||||
public final class WebSocketSessionHandler {
 | 
			
		||||
    private WebSocketSessionHandler() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static final Map<String, WebSocketSession> SESSION_MAP = new ConcurrentHashMap<>();
 | 
			
		||||
 | 
			
		||||
    public static void addSession(Object sessionKey, WebSocketSession session) {
 | 
			
		||||
        SESSION_MAP.put(sessionKey.toString(), session);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void removeSession(Object sessionKey) {
 | 
			
		||||
        SESSION_MAP.remove(sessionKey.toString());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static WebSocketSession getSession(Object sessionKey) {
 | 
			
		||||
        return SESSION_MAP.get(sessionKey.toString());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Collection<WebSocketSession> getSessions() {
 | 
			
		||||
        return SESSION_MAP.values();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Set<String> getSessionKeys() {
 | 
			
		||||
        return SESSION_MAP.keySet();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,31 @@
 | 
			
		||||
package cn.iocoder.yudao.framework.websocket.core;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.web.socket.TextMessage;
 | 
			
		||||
import org.springframework.web.socket.WebSocketSession;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class WebSocketUtils {
 | 
			
		||||
    public static boolean sendMessage(WebSocketSession seesion, String message) {
 | 
			
		||||
        if (seesion == null) {
 | 
			
		||||
            log.error("seesion 不存在");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        if (seesion.isOpen()) {
 | 
			
		||||
            try {
 | 
			
		||||
                seesion.sendMessage(new TextMessage(message));
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                log.error("WebSocket 消息发送异常 Session={} | msg= {} | exception={}", seesion, message, e);
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean sendMessage(Object sessionKey, String message) {
 | 
			
		||||
        WebSocketSession session = WebSocketSessionHandler.getSession(sessionKey);
 | 
			
		||||
        return sendMessage(session, message);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,49 @@
 | 
			
		||||
package cn.iocoder.yudao.framework.websocket.core;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
 | 
			
		||||
import org.springframework.web.socket.CloseStatus;
 | 
			
		||||
import org.springframework.web.socket.WebSocketHandler;
 | 
			
		||||
import org.springframework.web.socket.WebSocketSession;
 | 
			
		||||
import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
 | 
			
		||||
 | 
			
		||||
public class YudaoWebSocketHandlerDecorator extends WebSocketHandlerDecorator {
 | 
			
		||||
    public YudaoWebSocketHandlerDecorator(WebSocketHandler delegate) {
 | 
			
		||||
        super(delegate);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * websocket 连接时执行的动作
 | 
			
		||||
     * @param session websocket session 对象
 | 
			
		||||
     * @throws Exception 异常对象
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void afterConnectionEstablished(final WebSocketSession session) throws Exception {
 | 
			
		||||
        Object sessionKey = sessionKeyGen(session);
 | 
			
		||||
        WebSocketSessionHandler.addSession(sessionKey, session);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * websocket 关闭连接时执行的动作
 | 
			
		||||
     * @param session websocket session 对象
 | 
			
		||||
     * @param closeStatus 关闭状态对象
 | 
			
		||||
     * @throws Exception 异常对象
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void afterConnectionClosed(final WebSocketSession session, CloseStatus closeStatus) throws Exception {
 | 
			
		||||
        Object sessionKey = sessionKeyGen(session);
 | 
			
		||||
        WebSocketSessionHandler.removeSession(sessionKey);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Object sessionKeyGen(WebSocketSession webSocketSession) {
 | 
			
		||||
 | 
			
		||||
        Object obj = webSocketSession.getAttributes().get(WebSocketKeyDefine.LOGIN_USER);
 | 
			
		||||
 | 
			
		||||
        if (obj instanceof LoginUser) {
 | 
			
		||||
            LoginUser loginUser = (LoginUser) obj;
 | 
			
		||||
            // userId 作为唯一区分
 | 
			
		||||
            return String.valueOf(loginUser.getId());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
package cn.iocoder.yudao.framework.websocket;
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
cn.iocoder.yudao.framework.websocket.config.YudaoWebSocketAutoConfiguration
 | 
			
		||||
		Reference in New Issue
	
	Block a user