diff --git a/sa-token-demo/sa-token-demo-websocket-spring/.gitignore b/sa-token-demo/sa-token-demo-websocket-spring/.gitignore
new file mode 100644
index 00000000..99a6e767
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket-spring/.gitignore
@@ -0,0 +1,12 @@
+target/
+
+node_modules/
+bin/
+.settings/
+unpackage/
+.classpath
+.project
+
+.idea/
+
+.factorypath
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-websocket-spring/pom.xml b/sa-token-demo/sa-token-demo-websocket-spring/pom.xml
new file mode 100644
index 00000000..201500ae
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket-spring/pom.xml
@@ -0,0 +1,69 @@
+
+ 4.0.0
+ cn.dev33
+ sa-token-demo-websocket-spring
+ 0.0.1-SNAPSHOT
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.RELEASE
+
+
+
+
+
+
+ 1.29.0
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
+
+
+
+ cn.dev33
+ sa-token-spring-boot-starter
+ ${sa-token-version}
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/SaTokenWebSocketSpringApplication.java b/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/SaTokenWebSocketSpringApplication.java
new file mode 100644
index 00000000..431fab28
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/SaTokenWebSocketSpringApplication.java
@@ -0,0 +1,32 @@
+package com.pj;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import cn.dev33.satoken.SaManager;
+
+/**
+ * Sa-Token 整合 WebSocket 鉴权示例
+ * @author kong
+ *
+ */
+@SpringBootApplication
+public class SaTokenWebSocketSpringApplication {
+
+ /*
+ * 1、访问登录接口,拿到会话Token:
+ * http://localhost:8081/acc/doLogin?name=zhang&pwd=123456
+ *
+ * 2、找一个WebSocket在线测试页面进行连接,
+ * 例如:
+ * https://www.bejson.com/httputil/websocket/
+ * 然后连接地址:
+ * ws://localhost:8081/ws-connect?satoken=2e6db38f-1e78-40bc-aa8f-e8f1f77fbef5
+ */
+
+ public static void main(String[] args) {
+ SpringApplication.run(SaTokenWebSocketSpringApplication.class, args);
+ System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig());
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/test/LoginController.java b/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/test/LoginController.java
new file mode 100644
index 00000000..11abbe3c
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/test/LoginController.java
@@ -0,0 +1,48 @@
+package com.pj.test;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.util.SaResult;
+
+/**
+ * 登录测试
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/acc/")
+public class LoginController {
+
+ // 测试登录 ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456
+ @RequestMapping("doLogin")
+ public SaResult doLogin(String name, String pwd) {
+ // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
+ if("zhang".equals(name) && "123456".equals(pwd)) {
+ StpUtil.login(10001);
+ return SaResult.ok("登录成功").set("token", StpUtil.getTokenValue());
+ }
+ return SaResult.error("登录失败");
+ }
+
+ // 查询登录状态 ---- http://localhost:8081/acc/isLogin
+ @RequestMapping("isLogin")
+ public SaResult isLogin() {
+ return SaResult.ok("是否登录:" + StpUtil.isLogin());
+ }
+
+ // 查询 Token 信息 ---- http://localhost:8081/acc/tokenInfo
+ @RequestMapping("tokenInfo")
+ public SaResult tokenInfo() {
+ return SaResult.data(StpUtil.getTokenInfo());
+ }
+
+ // 测试注销 ---- http://localhost:8081/acc/logout
+ @RequestMapping("logout")
+ public SaResult logout() {
+ StpUtil.logout();
+ return SaResult.ok();
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/ws/MyWebSocketHandler.java b/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/ws/MyWebSocketHandler.java
new file mode 100644
index 00000000..990cc39d
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/ws/MyWebSocketHandler.java
@@ -0,0 +1,83 @@
+package com.pj.ws;
+
+import java.io.IOException;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.springframework.web.socket.CloseStatus;
+import org.springframework.web.socket.TextMessage;
+import org.springframework.web.socket.WebSocketSession;
+import org.springframework.web.socket.handler.TextWebSocketHandler;
+
+/**
+ * 处理 WebSocket 连接
+ *
+ * @author kong
+ * @date: 2022-2-11
+ */
+public class MyWebSocketHandler extends TextWebSocketHandler {
+
+ /**
+ * 固定前缀
+ */
+ private static final String USER_ID = "user_id_";
+
+ /**
+ * 存放Session集合,方便推送消息
+ */
+ private static ConcurrentHashMap webSocketSessionMaps = new ConcurrentHashMap<>();
+
+ // 监听:连接开启
+ @Override
+ public void afterConnectionEstablished(WebSocketSession session) throws Exception {
+
+ // put到集合,方便后续操作
+ String userId = session.getAttributes().get("userId").toString();
+ webSocketSessionMaps.put(USER_ID + userId, session);
+
+
+ // 给个提示
+ String tips = "Web-Socket 连接成功,sid=" + session.getId() + ",userId=" + userId;
+ System.out.println(tips);
+ sendMessage(session, tips);
+ }
+
+ // 监听:连接关闭
+ @Override
+ public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
+ // 从集合移除
+ String userId = session.getAttributes().get("userId").toString();
+ webSocketSessionMaps.remove(USER_ID + userId);
+
+ // 给个提示
+ String tips = "Web-Socket 连接关闭,sid=" + session.getId() + ",userId=" + userId;
+ System.out.println(tips);
+ }
+
+ // 收到消息
+ @Override
+ public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
+ System.out.println("sid为:" + session.getId() + ",发来:" + message);
+ }
+
+ // -----------
+
+ // 向指定客户端推送消息
+ public static void sendMessage(WebSocketSession session, String message) {
+ try {
+ System.out.println("向sid为:" + session.getId() + ",发送:" + message);
+ session.sendMessage(new TextMessage(message));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // 向指定用户推送消息
+ public static void sendMessage(long userId, String message) {
+ WebSocketSession session = webSocketSessionMaps.get(USER_ID + userId);
+ if(session != null) {
+ sendMessage(session, message);
+ }
+ }
+
+}
+
diff --git a/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/ws/WebSocketConfig.java b/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/ws/WebSocketConfig.java
new file mode 100644
index 00000000..186b52be
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/ws/WebSocketConfig.java
@@ -0,0 +1,30 @@
+package com.pj.ws;
+
+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;
+
+/**
+ * WebSocket 相关配置
+ *
+ * @author kong
+ * @date: 2022-2-11
+ */
+@Configuration
+@EnableWebSocket
+public class WebSocketConfig implements WebSocketConfigurer {
+
+ // 注册 WebSocket 处理器
+ @Override
+ public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
+ webSocketHandlerRegistry
+ // WebSocket 连接处理器
+ .addHandler(new MyWebSocketHandler(), "/ws-connect")
+ // WebSocket 拦截器
+ .addInterceptors(new WebSocketInterceptor())
+ // 允许跨域
+ .setAllowedOrigins("*");
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/ws/WebSocketInterceptor.java b/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/ws/WebSocketInterceptor.java
new file mode 100644
index 00000000..3643c1a5
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket-spring/src/main/java/com/pj/ws/WebSocketInterceptor.java
@@ -0,0 +1,45 @@
+package com.pj.ws;
+
+import java.util.Map;
+
+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 cn.dev33.satoken.stp.StpUtil;
+
+/**
+ * WebSocket 握手的前置拦截器
+ *
+ * @author kong
+ * @date: 2022-2-11
+ */
+public class WebSocketInterceptor implements HandshakeInterceptor {
+
+ // 握手之前触发 (return true 才会握手成功 )
+ @Override
+ public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler,
+ Map attr) {
+
+ System.out.println("---- 握手之前触发 " + StpUtil.getTokenValue());
+
+ // 未登录情况下拒绝握手
+ if(StpUtil.isLogin() == false) {
+ System.out.println("---- 未授权客户端,连接失败");
+ return false;
+ }
+
+ // 标记 userId,握手成功
+ attr.put("userId", StpUtil.getLoginIdAsLong());
+ return true;
+ }
+
+ // 握手之后触发
+ @Override
+ public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
+ Exception exception) {
+ System.out.println("---- 握手之后触发 ");
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-websocket-spring/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-websocket-spring/src/main/resources/application.yml
new file mode 100644
index 00000000..cb63067a
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket-spring/src/main/resources/application.yml
@@ -0,0 +1,49 @@
+# 端口
+server:
+ port: 8081
+
+# sa-token配置
+sa-token:
+ # token名称 (同时也是cookie名称)
+ token-name: satoken
+ # token有效期,单位s 默认30天, -1代表永不过期
+ timeout: 2592000
+ # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
+ activity-timeout: -1
+ # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
+ is-concurrent: true
+ # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
+ is-share: true
+ # token风格
+ token-style: uuid
+ # 是否输出操作日志
+ is-log: false
+
+spring:
+ # redis配置
+ redis:
+ # Redis数据库索引(默认为0)
+ database: 0
+ # Redis服务器地址
+ host: 127.0.0.1
+ # Redis服务器连接端口
+ port: 6379
+ # Redis服务器连接密码(默认为空)
+ password:
+ # 连接超时时间
+ timeout: 10s
+ lettuce:
+ pool:
+ # 连接池最大连接数
+ max-active: 200
+ # 连接池最大阻塞等待时间(使用负值表示没有限制)
+ max-wait: -1ms
+ # 连接池中的最大空闲连接
+ max-idle: 10
+ # 连接池中的最小空闲连接
+ min-idle: 0
+
+
+
+
+
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-websocket/.gitignore b/sa-token-demo/sa-token-demo-websocket/.gitignore
new file mode 100644
index 00000000..99a6e767
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket/.gitignore
@@ -0,0 +1,12 @@
+target/
+
+node_modules/
+bin/
+.settings/
+unpackage/
+.classpath
+.project
+
+.idea/
+
+.factorypath
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-websocket/pom.xml b/sa-token-demo/sa-token-demo-websocket/pom.xml
new file mode 100644
index 00000000..0b52bac6
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket/pom.xml
@@ -0,0 +1,69 @@
+
+ 4.0.0
+ cn.dev33
+ sa-token-demo-websocket
+ 0.0.1-SNAPSHOT
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.RELEASE
+
+
+
+
+
+
+ 1.29.0
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
+
+
+
+ cn.dev33
+ sa-token-spring-boot-starter
+ ${sa-token-version}
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-websocket/src/main/java/com/pj/SaTokenWebSocketApplication.java b/sa-token-demo/sa-token-demo-websocket/src/main/java/com/pj/SaTokenWebSocketApplication.java
new file mode 100644
index 00000000..6450ede8
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket/src/main/java/com/pj/SaTokenWebSocketApplication.java
@@ -0,0 +1,32 @@
+package com.pj;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import cn.dev33.satoken.SaManager;
+
+/**
+ * Sa-Token 整合 WebSocket 鉴权示例
+ * @author kong
+ *
+ */
+@SpringBootApplication
+public class SaTokenWebSocketApplication {
+
+ /*
+ * 1、访问登录接口,拿到会话Token:
+ * http://localhost:8081/acc/doLogin?name=zhang&pwd=123456
+ *
+ * 2、找一个WebSocket在线测试页面进行连接,
+ * 例如:
+ * https://www.bejson.com/httputil/websocket/
+ * 然后连接地址:
+ * ws://localhost:8081/ws-connect/2e6db38f-1e78-40bc-aa8f-e8f1f77fbef5
+ */
+
+ public static void main(String[] args) {
+ SpringApplication.run(SaTokenWebSocketApplication.class, args);
+ System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig());
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-websocket/src/main/java/com/pj/test/LoginController.java b/sa-token-demo/sa-token-demo-websocket/src/main/java/com/pj/test/LoginController.java
new file mode 100644
index 00000000..11abbe3c
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket/src/main/java/com/pj/test/LoginController.java
@@ -0,0 +1,48 @@
+package com.pj.test;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.util.SaResult;
+
+/**
+ * 登录测试
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/acc/")
+public class LoginController {
+
+ // 测试登录 ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456
+ @RequestMapping("doLogin")
+ public SaResult doLogin(String name, String pwd) {
+ // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
+ if("zhang".equals(name) && "123456".equals(pwd)) {
+ StpUtil.login(10001);
+ return SaResult.ok("登录成功").set("token", StpUtil.getTokenValue());
+ }
+ return SaResult.error("登录失败");
+ }
+
+ // 查询登录状态 ---- http://localhost:8081/acc/isLogin
+ @RequestMapping("isLogin")
+ public SaResult isLogin() {
+ return SaResult.ok("是否登录:" + StpUtil.isLogin());
+ }
+
+ // 查询 Token 信息 ---- http://localhost:8081/acc/tokenInfo
+ @RequestMapping("tokenInfo")
+ public SaResult tokenInfo() {
+ return SaResult.data(StpUtil.getTokenInfo());
+ }
+
+ // 测试注销 ---- http://localhost:8081/acc/logout
+ @RequestMapping("logout")
+ public SaResult logout() {
+ StpUtil.logout();
+ return SaResult.ok();
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-websocket/src/main/java/com/pj/ws/WebSocketConfig.java b/sa-token-demo/sa-token-demo-websocket/src/main/java/com/pj/ws/WebSocketConfig.java
new file mode 100644
index 00000000..356393ef
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket/src/main/java/com/pj/ws/WebSocketConfig.java
@@ -0,0 +1,18 @@
+package com.pj.ws;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * 开启WebSocket支持
+ */
+@Configuration
+public class WebSocketConfig {
+
+ @Bean
+ public ServerEndpointExporter serverEndpointExporter() {
+ return new ServerEndpointExporter();
+ }
+
+}
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-websocket/src/main/java/com/pj/ws/WebSocketConnect.java b/sa-token-demo/sa-token-demo-websocket/src/main/java/com/pj/ws/WebSocketConnect.java
new file mode 100644
index 00000000..c99e701f
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket/src/main/java/com/pj/ws/WebSocketConnect.java
@@ -0,0 +1,102 @@
+package com.pj.ws;
+
+import java.io.IOException;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.websocket.OnClose;
+import javax.websocket.OnError;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+
+import org.springframework.stereotype.Component;
+
+import cn.dev33.satoken.exception.SaTokenException;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.util.SaFoxUtil;
+
+/**
+ * WebSocket 连接测试
+ */
+@Component
+@ServerEndpoint("/ws-connect/{satoken}")
+public class WebSocketConnect {
+
+ /**
+ * 固定前缀
+ */
+ private static final String USER_ID = "user_id_";
+
+ /**
+ * 存放Session集合,方便推送消息 (javax.websocket.Session)
+ */
+ private static ConcurrentHashMap sessionMap = new ConcurrentHashMap<>();
+
+ // 监听:连接成功
+ @OnOpen
+ public void onOpen(Session session, @PathParam("satoken") String satoken) throws IOException {
+
+ // 根据 token 获取对应的 userId
+ Object loginId = StpUtil.getLoginIdByToken(satoken);
+ if(loginId == null) {
+ session.close();
+ throw new SaTokenException("连接失败,无效Token:" + satoken);
+ }
+
+ // put到集合,方便后续操作
+ long userId = SaFoxUtil.getValueByType(loginId, long.class);
+ sessionMap.put(USER_ID + userId, session);
+
+ // 给个提示
+ String tips = "Web-Socket 连接成功,sid=" + session.getId() + ",userId=" + userId;
+ System.out.println(tips);
+ sendMessage(session, tips);
+ }
+
+ // 监听: 连接关闭
+ @OnClose
+ public void onClose(Session session) {
+ System.out.println("连接关闭,sid=" + session.getId());
+ for (String key : sessionMap.keySet()) {
+ if(sessionMap.get(key).getId().equals(session.getId())) {
+ sessionMap.remove(key);
+ }
+ }
+ }
+
+ // 监听:收到客户端发送的消息
+ @OnMessage
+ public void onMessage(Session session, String message) {
+ System.out.println("sid为:" + session.getId() + ",发来:" + message);
+ }
+
+ // 监听:发生异常
+ @OnError
+ public void onError(Session session, Throwable error) {
+ System.out.println("sid为:" + session.getId() + ",发生错误");
+ error.printStackTrace();
+ }
+
+ // ---------
+
+ // 向指定客户端推送消息
+ public static void sendMessage(Session session, String message) {
+ try {
+ System.out.println("向sid为:" + session.getId() + ",发送:" + message);
+ session.getBasicRemote().sendText(message);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // 向指定用户推送消息
+ public static void sendMessage(long userId, String message) {
+ Session session = sessionMap.get(USER_ID + userId);
+ if(session != null) {
+ sendMessage(session, message);
+ }
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-websocket/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-websocket/src/main/resources/application.yml
new file mode 100644
index 00000000..cb63067a
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-websocket/src/main/resources/application.yml
@@ -0,0 +1,49 @@
+# 端口
+server:
+ port: 8081
+
+# sa-token配置
+sa-token:
+ # token名称 (同时也是cookie名称)
+ token-name: satoken
+ # token有效期,单位s 默认30天, -1代表永不过期
+ timeout: 2592000
+ # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
+ activity-timeout: -1
+ # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
+ is-concurrent: true
+ # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
+ is-share: true
+ # token风格
+ token-style: uuid
+ # 是否输出操作日志
+ is-log: false
+
+spring:
+ # redis配置
+ redis:
+ # Redis数据库索引(默认为0)
+ database: 0
+ # Redis服务器地址
+ host: 127.0.0.1
+ # Redis服务器连接端口
+ port: 6379
+ # Redis服务器连接密码(默认为空)
+ password:
+ # 连接超时时间
+ timeout: 10s
+ lettuce:
+ pool:
+ # 连接池最大连接数
+ max-active: 200
+ # 连接池最大阻塞等待时间(使用负值表示没有限制)
+ max-wait: -1ms
+ # 连接池中的最大空闲连接
+ max-idle: 10
+ # 连接池中的最小空闲连接
+ min-idle: 0
+
+
+
+
+
\ No newline at end of file
diff --git a/sa-token-doc/doc/start/download.md b/sa-token-doc/doc/start/download.md
index a6921673..c11de14b 100644
--- a/sa-token-doc/doc/start/download.md
+++ b/sa-token-doc/doc/start/download.md
@@ -120,6 +120,8 @@ implementation 'cn.dev33:sa-token-core:${sa.top.version}'
├── sa-token-demo-sso-client-h5 // [示例] Sa-Token 集成 SSO单点登录-client应用端 (前后端分离)
├── sa-token-demo-oauth2-server // [示例] Sa-Token 集成 OAuth2.0 (服务端)
├── sa-token-demo-oauth2-client // [示例] Sa-Token 集成 OAuth2.0 (客户端)
+ ├── sa-token-demo-websocket // [示例] Sa-Token 集成 Web-Socket 鉴权示例
+ ├── sa-token-demo-websocket-spring // [示例] Sa-Token 集成 Web-Socket(Spring封装版) 鉴权示例
├── sa-token-test // [测试] Sa-Token 单元测试合集
├── sa-token-core-test // [测试] Sa-Token Core核心包单元测试
├── sa-token-springboot-test // [测试] Sa-Token SpringBoot 整合测试