diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml
index cd599ffdf..7b056c46b 100644
--- a/yudao-dependencies/pom.xml
+++ b/yudao-dependencies/pom.xml
@@ -23,8 +23,8 @@
2.5
1.2.15
- 3.5.3
- 3.5.2
+ 3.5.3.1
+ 3.5.3.1
3.6.1
3.18.0
diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml
index 1928aa88c..3bfc020ba 100644
--- a/yudao-framework/pom.xml
+++ b/yudao-framework/pom.xml
@@ -40,6 +40,7 @@
yudao-spring-boot-starter-flowable
yudao-spring-boot-starter-captcha
+ yudao-spring-boot-starter-websocket
yudao-framework
diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml b/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml
new file mode 100644
index 000000000..320e52c48
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml
@@ -0,0 +1,37 @@
+
+
+
+ cn.iocoder.boot
+ yudao-framework
+ ${revision}
+
+ 4.0.0
+ yudao-spring-boot-starter-websocket
+ jar
+
+ ${project.artifactId}
+ WebSocket
+ https://github.com/YunaiV/ruoyi-vue-pro
+
+
+
+
+
+ cn.iocoder.boot
+ yudao-common
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-security
+
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
+
+
+
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/WebSocketHandlerConfig.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/WebSocketHandlerConfig.java
new file mode 100644
index 000000000..02c3415d5
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/WebSocketHandlerConfig.java
@@ -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();
+ }
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/WebSocketProperties.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/WebSocketProperties.java
new file mode 100644
index 000000000..0ab1b498f
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/WebSocketProperties.java
@@ -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;
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java
new file mode 100644
index 000000000..f8c50ae6a
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java
@@ -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,
+ WebSocketHandler webSocketHandler,
+ WebSocketProperties webSocketProperties) {
+
+ return registry -> registry
+ .addHandler(webSocketHandler, webSocketProperties.getPath())
+ .addInterceptors(handshakeInterceptor.toArray(new HandshakeInterceptor[0]));
+ }
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/UserHandshakeInterceptor.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/UserHandshakeInterceptor.java
new file mode 100644
index 000000000..3f2fa4ec3
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/UserHandshakeInterceptor.java
@@ -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 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) {
+
+ }
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/WebSocketKeyDefine.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/WebSocketKeyDefine.java
new file mode 100644
index 000000000..f75ebc41c
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/WebSocketKeyDefine.java
@@ -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";
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/WebSocketMessageDO.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/WebSocketMessageDO.java
new file mode 100644
index 000000000..7bb348e99
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/WebSocketMessageDO.java
@@ -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