From cc079e8bf422825bf9a96ddbd4329fc77d3cbf2c Mon Sep 17 00:00:00 2001 From: Charles7c Date: Tue, 4 Jun 2024 22:43:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(messaging/websocket):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E6=A8=A1=E5=9D=97=20-=20WebSocket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/constant/PropertiesConstants.java | 10 ++ continew-starter-dependencies/pom.xml | 7 ++ .../pom.xml | 22 ++++ .../WebSocketAutoConfiguration.java | 101 ++++++++++++++++++ .../autoconfigure/WebSocketProperties.java | 90 ++++++++++++++++ .../websocket/core/CurrentUserProvider.java | 37 +++++++ .../websocket/core/WebSocketHandler.java | 71 ++++++++++++ .../websocket/core/WebSocketInterceptor.java | 66 ++++++++++++ .../websocket/dao/WebSocketSessionDao.java | 51 +++++++++ .../dao/WebSocketSessionDaoDefaultImpl.java | 48 +++++++++ .../websocket/model/CurrentUser.java | 58 ++++++++++ .../websocket/util/WebSocketUtils.java | 82 ++++++++++++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + continew-starter-messaging/pom.xml | 1 + continew-starter-web/pom.xml | 7 -- .../autoconfigure/cors/CorsProperties.java | 4 +- 16 files changed, 647 insertions(+), 9 deletions(-) create mode 100644 continew-starter-messaging/continew-starter-messaging-websocket/pom.xml create mode 100644 continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/autoconfigure/WebSocketAutoConfiguration.java create mode 100644 continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/autoconfigure/WebSocketProperties.java create mode 100644 continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/core/CurrentUserProvider.java create mode 100644 continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/core/WebSocketHandler.java create mode 100644 continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/core/WebSocketInterceptor.java create mode 100644 continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/dao/WebSocketSessionDao.java create mode 100644 continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/dao/WebSocketSessionDaoDefaultImpl.java create mode 100644 continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/model/CurrentUser.java create mode 100644 continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/util/WebSocketUtils.java create mode 100644 continew-starter-messaging/continew-starter-messaging-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/continew-starter-core/src/main/java/top/continew/starter/core/constant/PropertiesConstants.java b/continew-starter-core/src/main/java/top/continew/starter/core/constant/PropertiesConstants.java index 2935fc99..edb8d4b0 100644 --- a/continew-starter-core/src/main/java/top/continew/starter/core/constant/PropertiesConstants.java +++ b/continew-starter-core/src/main/java/top/continew/starter/core/constant/PropertiesConstants.java @@ -114,6 +114,16 @@ public class PropertiesConstants { */ public static final String CAPTCHA_BEHAVIOR = CAPTCHA + StringConstants.DOT + "behavior"; + /** + * 消息配置 + */ + public static final String MESSAGING = CONTINEW_STARTER + StringConstants.DOT + "messaging"; + + /** + * WebSocket 配置 + */ + public static final String MESSAGING_WEBSOCKET = MESSAGING + StringConstants.DOT + "websocket"; + private PropertiesConstants() { } } diff --git a/continew-starter-dependencies/pom.xml b/continew-starter-dependencies/pom.xml index 9a5a8efb..3db3648a 100644 --- a/continew-starter-dependencies/pom.xml +++ b/continew-starter-dependencies/pom.xml @@ -389,6 +389,13 @@ ${revision} + + + top.continew + continew-starter-messaging-websocket + ${revision} + + top.continew diff --git a/continew-starter-messaging/continew-starter-messaging-websocket/pom.xml b/continew-starter-messaging/continew-starter-messaging-websocket/pom.xml new file mode 100644 index 00000000..b0a901a7 --- /dev/null +++ b/continew-starter-messaging/continew-starter-messaging-websocket/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + + top.continew + continew-starter-messaging + ${revision} + + + continew-starter-messaging-websocket + ContiNew Starter 消息模块 - WebSocket + + + + + org.springframework.boot + spring-boot-starter-websocket + + + \ No newline at end of file diff --git a/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/autoconfigure/WebSocketAutoConfiguration.java b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/autoconfigure/WebSocketAutoConfiguration.java new file mode 100644 index 00000000..b00469f4 --- /dev/null +++ b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/autoconfigure/WebSocketAutoConfiguration.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * 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 + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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."); + } +} diff --git a/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/autoconfigure/WebSocketProperties.java b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/autoconfigure/WebSocketProperties.java new file mode 100644 index 00000000..a9170ff9 --- /dev/null +++ b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/autoconfigure/WebSocketProperties.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * 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 + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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 ALL = Collections.singletonList(StringConstants.ASTERISK); + + /** + * 是否启用 WebSocket + */ + private boolean enabled = false; + + /** + * 路径 + */ + private String path = StringConstants.SLASH + "websocket"; + + /** + * 允许跨域的域名 + */ + private List 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 getAllowedOrigins() { + return allowedOrigins; + } + + public void setAllowedOrigins(List allowedOrigins) { + this.allowedOrigins = allowedOrigins; + } + + public String getCurrentUserKey() { + return currentUserKey; + } + + public void setCurrentUserKey(String currentUserKey) { + this.currentUserKey = currentUserKey; + } +} diff --git a/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/core/CurrentUserProvider.java b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/core/CurrentUserProvider.java new file mode 100644 index 00000000..bb8ac3fe --- /dev/null +++ b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/core/CurrentUserProvider.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * 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 + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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); +} diff --git a/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/core/WebSocketHandler.java b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/core/WebSocketHandler.java new file mode 100644 index 00000000..11261a88 --- /dev/null +++ b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/core/WebSocketHandler.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * 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 + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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); + } +} diff --git a/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/core/WebSocketInterceptor.java b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/core/WebSocketInterceptor.java new file mode 100644 index 00000000..57e0dfb6 --- /dev/null +++ b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/core/WebSocketInterceptor.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * 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 + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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 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); + } +} diff --git a/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/dao/WebSocketSessionDao.java b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/dao/WebSocketSessionDao.java new file mode 100644 index 00000000..e24ddc42 --- /dev/null +++ b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/dao/WebSocketSessionDao.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * 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 + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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); +} diff --git a/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/dao/WebSocketSessionDaoDefaultImpl.java b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/dao/WebSocketSessionDaoDefaultImpl.java new file mode 100644 index 00000000..f83a81b7 --- /dev/null +++ b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/dao/WebSocketSessionDaoDefaultImpl.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * 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 + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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 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); + } +} diff --git a/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/model/CurrentUser.java b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/model/CurrentUser.java new file mode 100644 index 00000000..917b1987 --- /dev/null +++ b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/model/CurrentUser.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * 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 + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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; + } +} diff --git a/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/util/WebSocketUtils.java b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/util/WebSocketUtils.java new file mode 100644 index 00000000..88bd1d81 --- /dev/null +++ b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/java/top/continew/starter/messaging/websocket/util/WebSocketUtils.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * 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 + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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); + } + } +} diff --git a/continew-starter-messaging/continew-starter-messaging-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..6b2c0261 --- /dev/null +++ b/continew-starter-messaging/continew-starter-messaging-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +top.continew.starter.messaging.websocket.autoconfigure.WebSocketAutoConfiguration \ No newline at end of file diff --git a/continew-starter-messaging/pom.xml b/continew-starter-messaging/pom.xml index 2aa5efc6..533a614f 100644 --- a/continew-starter-messaging/pom.xml +++ b/continew-starter-messaging/pom.xml @@ -15,6 +15,7 @@ continew-starter-messaging-mail + continew-starter-messaging-websocket diff --git a/continew-starter-web/pom.xml b/continew-starter-web/pom.xml index 88e2317f..3a97f379 100644 --- a/continew-starter-web/pom.xml +++ b/continew-starter-web/pom.xml @@ -30,13 +30,6 @@ org.springframework.boot spring-boot-starter-undertow - - - - io.undertow - undertow-websockets-jsr - - diff --git a/continew-starter-web/src/main/java/top/continew/starter/web/autoconfigure/cors/CorsProperties.java b/continew-starter-web/src/main/java/top/continew/starter/web/autoconfigure/cors/CorsProperties.java index f6f0ab18..302930b3 100644 --- a/continew-starter-web/src/main/java/top/continew/starter/web/autoconfigure/cors/CorsProperties.java +++ b/continew-starter-web/src/main/java/top/continew/starter/web/autoconfigure/cors/CorsProperties.java @@ -33,6 +33,8 @@ import java.util.List; @ConfigurationProperties(PropertiesConstants.CORS) public class CorsProperties { + private static final List ALL = Collections.singletonList(StringConstants.ASTERISK); + /** * 是否启用跨域配置 */ @@ -58,8 +60,6 @@ public class CorsProperties { */ private List exposedHeaders = new ArrayList<>(); - private static final List ALL = Collections.singletonList(StringConstants.ASTERISK); - public boolean isEnabled() { return enabled; }