mirror of
				https://github.com/continew-org/continew-starter.git
				synced 2025-10-31 22:57:19 +08:00 
			
		
		
		
	feat(messaging/websocket): 新增消息模块 - WebSocket
This commit is contained in:
		| @@ -0,0 +1,22 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||
|          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
|          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
|     <parent> | ||||
|         <groupId>top.continew</groupId> | ||||
|         <artifactId>continew-starter-messaging</artifactId> | ||||
|         <version>${revision}</version> | ||||
|     </parent> | ||||
|  | ||||
|     <artifactId>continew-starter-messaging-websocket</artifactId> | ||||
|     <description>ContiNew Starter 消息模块 - WebSocket</description> | ||||
|  | ||||
|     <dependencies> | ||||
|         <!-- WebSocket 支持 --> | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.boot</groupId> | ||||
|             <artifactId>spring-boot-starter-websocket</artifactId> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
| </project> | ||||
| @@ -0,0 +1,101 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.messaging.websocket.autoconfigure; | ||||
|  | ||||
| import cn.hutool.extra.spring.SpringUtil; | ||||
| import jakarta.annotation.PostConstruct; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.factory.NoSuchBeanDefinitionException; | ||||
| 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.EnableWebSocket; | ||||
| import org.springframework.web.socket.config.annotation.WebSocketConfigurer; | ||||
| import org.springframework.web.socket.server.HandshakeInterceptor; | ||||
| import top.continew.starter.core.constant.PropertiesConstants; | ||||
| import top.continew.starter.messaging.websocket.core.CurrentUserProvider; | ||||
| import top.continew.starter.messaging.websocket.core.WebSocketInterceptor; | ||||
| import top.continew.starter.messaging.websocket.dao.WebSocketSessionDao; | ||||
| import top.continew.starter.messaging.websocket.dao.WebSocketSessionDaoDefaultImpl; | ||||
|  | ||||
| /** | ||||
|  * WebSocket 自动配置 | ||||
|  * | ||||
|  * @author WeiRan | ||||
|  * @author Charles7c | ||||
|  * @since 2.1.0 | ||||
|  */ | ||||
| @AutoConfiguration | ||||
| @EnableWebSocket | ||||
| @EnableConfigurationProperties(WebSocketProperties.class) | ||||
| @ConditionalOnProperty(prefix = PropertiesConstants.MESSAGING_WEBSOCKET, name = PropertiesConstants.ENABLED, havingValue = "true") | ||||
| public class WebSocketAutoConfiguration { | ||||
|  | ||||
|     private static final Logger log = LoggerFactory.getLogger(WebSocketAutoConfiguration.class); | ||||
|     private final WebSocketProperties properties; | ||||
|  | ||||
|     public WebSocketAutoConfiguration(WebSocketProperties properties) { | ||||
|         this.properties = properties; | ||||
|     } | ||||
|  | ||||
|     @Bean | ||||
|     public WebSocketConfigurer webSocketConfigurer(WebSocketHandler handler, HandshakeInterceptor interceptor) { | ||||
|         return registry -> registry.addHandler(handler, properties.getPath()) | ||||
|             .addInterceptors(interceptor) | ||||
|             .setAllowedOrigins(properties.getAllowedOrigins().toArray(String[]::new)); | ||||
|     } | ||||
|  | ||||
|     @Bean | ||||
|     @ConditionalOnMissingBean | ||||
|     public WebSocketHandler webSocketHandler() { | ||||
|         return new top.continew.starter.messaging.websocket.core.WebSocketHandler(properties, SpringUtil | ||||
|             .getBean(WebSocketSessionDao.class)); | ||||
|     } | ||||
|  | ||||
|     @Bean | ||||
|     @ConditionalOnMissingBean | ||||
|     public HandshakeInterceptor handshakeInterceptor() { | ||||
|         return new WebSocketInterceptor(properties, SpringUtil.getBean(CurrentUserProvider.class)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * WebSocket 会话 DAO | ||||
|      */ | ||||
|     @Bean | ||||
|     @ConditionalOnMissingBean | ||||
|     public WebSocketSessionDao webSocketSessionDao() { | ||||
|         return new WebSocketSessionDaoDefaultImpl(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 当前用户 Provider(如不提供,则报错) | ||||
|      */ | ||||
|     @Bean | ||||
|     @ConditionalOnMissingBean | ||||
|     public CurrentUserProvider currentUserProvider() { | ||||
|         throw new NoSuchBeanDefinitionException(CurrentUserProvider.class); | ||||
|     } | ||||
|  | ||||
|     @PostConstruct | ||||
|     public void postConstruct() { | ||||
|         log.debug("[ContiNew Starter] - Auto Configuration 'Messaging-WebSocket' completed initialization."); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,90 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.messaging.websocket.autoconfigure; | ||||
|  | ||||
| import org.springframework.boot.context.properties.ConfigurationProperties; | ||||
| import top.continew.starter.core.constant.PropertiesConstants; | ||||
| import top.continew.starter.core.constant.StringConstants; | ||||
|  | ||||
| import java.awt.*; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * WebSocket 配置属性 | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2.1.0 | ||||
|  */ | ||||
| @ConfigurationProperties(PropertiesConstants.MESSAGING_WEBSOCKET) | ||||
| public class WebSocketProperties { | ||||
|  | ||||
|     private static final List<String> ALL = Collections.singletonList(StringConstants.ASTERISK); | ||||
|  | ||||
|     /** | ||||
|      * 是否启用 WebSocket | ||||
|      */ | ||||
|     private boolean enabled = false; | ||||
|  | ||||
|     /** | ||||
|      * 路径 | ||||
|      */ | ||||
|     private String path = StringConstants.SLASH + "websocket"; | ||||
|  | ||||
|     /** | ||||
|      * 允许跨域的域名 | ||||
|      */ | ||||
|     private List<String> allowedOrigins = new ArrayList<>(ALL); | ||||
|  | ||||
|     /** | ||||
|      * 当前登录用户 Key | ||||
|      */ | ||||
|     private String currentUserKey = "CURRENT_USER"; | ||||
|  | ||||
|     public boolean isEnabled() { | ||||
|         return enabled; | ||||
|     } | ||||
|  | ||||
|     public void setEnabled(boolean enabled) { | ||||
|         this.enabled = enabled; | ||||
|     } | ||||
|  | ||||
|     public String getPath() { | ||||
|         return path; | ||||
|     } | ||||
|  | ||||
|     public void setPath(String path) { | ||||
|         this.path = path; | ||||
|     } | ||||
|  | ||||
|     public List<String> getAllowedOrigins() { | ||||
|         return allowedOrigins; | ||||
|     } | ||||
|  | ||||
|     public void setAllowedOrigins(List<String> allowedOrigins) { | ||||
|         this.allowedOrigins = allowedOrigins; | ||||
|     } | ||||
|  | ||||
|     public String getCurrentUserKey() { | ||||
|         return currentUserKey; | ||||
|     } | ||||
|  | ||||
|     public void setCurrentUserKey(String currentUserKey) { | ||||
|         this.currentUserKey = currentUserKey; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,37 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.messaging.websocket.core; | ||||
|  | ||||
| import org.springframework.http.server.ServletServerHttpRequest; | ||||
| import top.continew.starter.messaging.websocket.model.CurrentUser; | ||||
|  | ||||
| /** | ||||
|  * 当前登录用户 Provider | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2.1.0 | ||||
|  */ | ||||
| public interface CurrentUserProvider { | ||||
|  | ||||
|     /** | ||||
|      * 获取当前登录用户 | ||||
|      * | ||||
|      * @param request 请求对象 | ||||
|      * @return 当前登录用户 | ||||
|      */ | ||||
|     CurrentUser getCurrentUser(ServletServerHttpRequest request); | ||||
| } | ||||
| @@ -0,0 +1,71 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.messaging.websocket.core; | ||||
|  | ||||
| import cn.hutool.core.convert.Convert; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.web.socket.CloseStatus; | ||||
| import org.springframework.web.socket.TextMessage; | ||||
| import org.springframework.web.socket.WebSocketSession; | ||||
| import org.springframework.web.socket.handler.AbstractWebSocketHandler; | ||||
| import top.continew.starter.messaging.websocket.autoconfigure.WebSocketProperties; | ||||
| import top.continew.starter.messaging.websocket.dao.WebSocketSessionDao; | ||||
|  | ||||
| /** | ||||
|  * WebSocket 处理器 | ||||
|  * | ||||
|  * @author WeiRan | ||||
|  * @author Charles7c | ||||
|  * @since 2.1.0 | ||||
|  */ | ||||
| public class WebSocketHandler extends AbstractWebSocketHandler { | ||||
|  | ||||
|     private static final Logger log = LoggerFactory.getLogger(WebSocketHandler.class); | ||||
|     private final WebSocketProperties webSocketProperties; | ||||
|     private final WebSocketSessionDao webSocketSessionDao; | ||||
|  | ||||
|     public WebSocketHandler(WebSocketProperties webSocketProperties, WebSocketSessionDao webSocketSessionDao) { | ||||
|         this.webSocketProperties = webSocketProperties; | ||||
|         this.webSocketSessionDao = webSocketSessionDao; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { | ||||
|         log.info("WebSocket receive message. sessionId: {}, message: {}.", session.getId(), message.getPayload()); | ||||
|         super.handleTextMessage(session, message); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void afterConnectionEstablished(WebSocketSession session) { | ||||
|         String sessionKey = Convert.toStr(session.getAttributes().get(webSocketProperties.getCurrentUserKey())); | ||||
|         webSocketSessionDao.add(sessionKey, session); | ||||
|         log.info("WebSocket connect successfully. sessionKey: {}.", sessionKey); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { | ||||
|         String sessionKey = Convert.toStr(session.getAttributes().get(webSocketProperties.getCurrentUserKey())); | ||||
|         webSocketSessionDao.delete(sessionKey); | ||||
|         log.info("WebSocket connect closed. sessionKey: {}.", sessionKey); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void handleTransportError(WebSocketSession session, Throwable exception) { | ||||
|         log.error("WebSocket transport error. sessionId: {}.", session.getId(), exception); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,66 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.messaging.websocket.core; | ||||
|  | ||||
| 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.web.socket.WebSocketHandler; | ||||
| import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; | ||||
| import top.continew.starter.messaging.websocket.autoconfigure.WebSocketProperties; | ||||
| import top.continew.starter.messaging.websocket.model.CurrentUser; | ||||
|  | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * WebSocket 拦截器 | ||||
|  * | ||||
|  * @author WeiRan | ||||
|  * @author Charles7c | ||||
|  * @since 2.1.0 | ||||
|  */ | ||||
| public class WebSocketInterceptor extends HttpSessionHandshakeInterceptor { | ||||
|  | ||||
|     private static final Logger log = LoggerFactory.getLogger(WebSocketInterceptor.class); | ||||
|     private final WebSocketProperties webSocketProperties; | ||||
|     private final CurrentUserProvider currentUserProvider; | ||||
|  | ||||
|     public WebSocketInterceptor(WebSocketProperties webSocketProperties, CurrentUserProvider currentUserProvider) { | ||||
|         this.webSocketProperties = webSocketProperties; | ||||
|         this.currentUserProvider = currentUserProvider; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean beforeHandshake(ServerHttpRequest request, | ||||
|                                    ServerHttpResponse response, | ||||
|                                    WebSocketHandler wsHandler, | ||||
|                                    Map<String, Object> attributes) { | ||||
|         CurrentUser currentUser = currentUserProvider.getCurrentUser((ServletServerHttpRequest)request); | ||||
|         attributes.put(webSocketProperties.getCurrentUserKey(), currentUser.getUserId()); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void afterHandshake(ServerHttpRequest request, | ||||
|                                ServerHttpResponse response, | ||||
|                                WebSocketHandler wsHandler, | ||||
|                                Exception exception) { | ||||
|         super.afterHandshake(request, response, wsHandler, exception); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,51 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.messaging.websocket.dao; | ||||
|  | ||||
| import org.springframework.web.socket.WebSocketSession; | ||||
|  | ||||
| /** | ||||
|  * WebSocket 会话 DAO | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2.1.0 | ||||
|  */ | ||||
| public interface WebSocketSessionDao { | ||||
|  | ||||
|     /** | ||||
|      * 添加会话 | ||||
|      * | ||||
|      * @param key     会话 Key | ||||
|      * @param session 会话信息 | ||||
|      */ | ||||
|     void add(String key, WebSocketSession session); | ||||
|  | ||||
|     /** | ||||
|      * 删除会话 | ||||
|      * | ||||
|      * @param key 会话 Key | ||||
|      */ | ||||
|     void delete(String key); | ||||
|  | ||||
|     /** | ||||
|      * 获取会话 | ||||
|      * | ||||
|      * @param key 会话 Key | ||||
|      * @return 会话信息 | ||||
|      */ | ||||
|     WebSocketSession get(String key); | ||||
| } | ||||
| @@ -0,0 +1,48 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.messaging.websocket.dao; | ||||
|  | ||||
| import org.springframework.web.socket.WebSocketSession; | ||||
|  | ||||
| import java.util.Map; | ||||
| import java.util.concurrent.ConcurrentHashMap; | ||||
|  | ||||
| /** | ||||
|  * WebSocket 会话 DAO 默认实现 | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2.1.0 | ||||
|  */ | ||||
| public class WebSocketSessionDaoDefaultImpl implements WebSocketSessionDao { | ||||
|  | ||||
|     private static final Map<String, WebSocketSession> SESSION_MAP = new ConcurrentHashMap<>(); | ||||
|  | ||||
|     @Override | ||||
|     public void add(String key, WebSocketSession session) { | ||||
|         SESSION_MAP.put(key, session); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void delete(String key) { | ||||
|         SESSION_MAP.remove(key); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public WebSocketSession get(String key) { | ||||
|         return SESSION_MAP.get(key); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,58 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.messaging.websocket.model; | ||||
|  | ||||
| import java.io.Serial; | ||||
| import java.io.Serializable; | ||||
|  | ||||
| /** | ||||
|  * 当前登录用户信息 | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2.1.0 | ||||
|  */ | ||||
| public class CurrentUser implements Serializable { | ||||
|  | ||||
|     @Serial | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * 用户 ID | ||||
|      */ | ||||
|     private String userId; | ||||
|  | ||||
|     /** | ||||
|      * 扩展字段 | ||||
|      */ | ||||
|     private Object extend; | ||||
|  | ||||
|     public String getUserId() { | ||||
|         return userId; | ||||
|     } | ||||
|  | ||||
|     public void setUserId(String userId) { | ||||
|         this.userId = userId; | ||||
|     } | ||||
|  | ||||
|     public Object getExtend() { | ||||
|         return extend; | ||||
|     } | ||||
|  | ||||
|     public void setExtend(Object extend) { | ||||
|         this.extend = extend; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,82 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.messaging.websocket.util; | ||||
|  | ||||
| import cn.hutool.extra.spring.SpringUtil; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.web.socket.TextMessage; | ||||
| import org.springframework.web.socket.WebSocketMessage; | ||||
| import org.springframework.web.socket.WebSocketSession; | ||||
| import top.continew.starter.messaging.websocket.dao.WebSocketSessionDao; | ||||
|  | ||||
| import java.io.IOException; | ||||
|  | ||||
| /** | ||||
|  * WebSocket 工具类 | ||||
|  * | ||||
|  * @author WeiRan | ||||
|  * @author Charles7c | ||||
|  * @since 2.1.0 | ||||
|  */ | ||||
| public class WebSocketUtils { | ||||
|  | ||||
|     private static final Logger log = LoggerFactory.getLogger(WebSocketUtils.class); | ||||
|     private static final WebSocketSessionDao SESSION_DAO = SpringUtil.getBean(WebSocketSessionDao.class); | ||||
|  | ||||
|     private WebSocketUtils() { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 发送消息 | ||||
|      * | ||||
|      * @param sessionKey 会话 Key | ||||
|      * @param message    消息内容 | ||||
|      */ | ||||
|     public static void sendMessage(String sessionKey, String message) { | ||||
|         WebSocketSession session = SESSION_DAO.get(sessionKey); | ||||
|         sendMessage(session, message); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 发送消息 | ||||
|      * | ||||
|      * @param session 会话 | ||||
|      * @param message 消息内容 | ||||
|      */ | ||||
|     public static void sendMessage(WebSocketSession session, String message) { | ||||
|         sendMessage(session, new TextMessage(message)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 发送消息 | ||||
|      * | ||||
|      * @param session 会话 | ||||
|      * @param message 消息内容 | ||||
|      */ | ||||
|     public static void sendMessage(WebSocketSession session, WebSocketMessage<?> message) { | ||||
|         if (session == null || !session.isOpen()) { | ||||
|             log.warn("WebSocket session closed."); | ||||
|             return; | ||||
|         } | ||||
|         try { | ||||
|             session.sendMessage(message); | ||||
|         } catch (IOException e) { | ||||
|             log.error("WebSocket send message failed. sessionId: {}.", session.getId(), e); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1 @@ | ||||
| top.continew.starter.messaging.websocket.autoconfigure.WebSocketAutoConfiguration | ||||
		Reference in New Issue
	
	Block a user