diff --git a/MEMO/3--sa-token_最新版所有依赖.txt b/MEMO/3--sa-token_最新版所有依赖.txt new file mode 100644 index 00000000..a2f31bb3 --- /dev/null +++ b/MEMO/3--sa-token_最新版所有依赖.txt @@ -0,0 +1,344 @@ + + + cn.dev33 + sa-token-bom + 1.45.0 + pom + import + + + + + cn.dev33 + sa-token-core + 1.45.0 + + + + + cn.dev33 + sa-token-spring-boot-starter + 1.45.0 + + + + + cn.dev33 + sa-token-spring-boot3-starter + 1.45.0 + + + + + cn.dev33 + sa-token-spring-boot4-starter + 1.45.0 + + + + + cn.dev33 + sa-token-reactor-spring-boot-starter + 1.45.0 + + + + + cn.dev33 + sa-token-reactor-spring-boot3-starter + 1.45.0 + + + + + cn.dev33 + sa-token-reactor-spring-boot4-starter + 1.45.0 + + + + + cn.dev33 + sa-token-jboot-plugin + 1.45.0 + + + + + cn.dev33 + sa-token-jfinal-plugin + 1.45.0 + + + + + cn.dev33 + sa-token-loveqq-boot-starter + 1.45.0 + + + + + cn.dev33 + sa-token-servlet + 1.45.0 + + + + + cn.dev33 + sa-token-jakarta-servlet + 1.45.0 + + + + + cn.dev33 + sa-token-plugin + 1.45.0 + + + + + cn.dev33 + sa-token-alone-redis + 1.45.0 + + + + + cn.dev33 + sa-token-redis-template + 1.45.0 + + + + + cn.dev33 + sa-token-redis-template-jdk-serializer + 1.45.0 + + + + + cn.dev33 + sa-token-redis-jackson + 1.45.0 + + + + + cn.dev33 + sa-token-redisson + 1.45.0 + + + + + cn.dev33 + sa-token-redisson-spring-boot-starter + 1.45.0 + + + + + cn.dev33 + sa-token-redisx + 1.45.0 + + + + + cn.dev33 + sa-token-hutool-timed-cache + 1.45.0 + + + + + cn.dev33 + sa-token-caffeine + 1.45.0 + + + + + cn.dev33 + sa-token-jackson + 1.45.0 + + + + + cn.dev33 + sa-token-jackson3 + 1.45.0 + + + + + cn.dev33 + sa-token-fastjson + 1.45.0 + + + + + cn.dev33 + sa-token-fastjson2 + 1.45.0 + + + + + cn.dev33 + sa-token-snack3 + 1.45.0 + + + + + cn.dev33 + sa-token-snack4 + 1.45.0 + + + + + cn.dev33 + sa-token-serializer-features + 1.45.0 + + + + + cn.dev33 + sa-token-thymeleaf + 1.45.0 + + + + + cn.dev33 + sa-token-freemarker + 1.45.0 + + + + + cn.dev33 + sa-token-dubbo + 1.45.0 + + + + + cn.dev33 + sa-token-dubbo3 + 1.45.0 + + + + + cn.dev33 + sa-token-grpc + 1.45.0 + + + + + cn.dev33 + sa-token-forest + 1.45.0 + + + + + cn.dev33 + sa-token-okhttps + 1.45.0 + + + + + cn.dev33 + sa-token-jwt + 1.45.0 + + + + + cn.dev33 + sa-token-temp-jwt + 1.45.0 + + + + + cn.dev33 + sa-token-oauth2 + 1.45.0 + + + + + cn.dev33 + sa-token-apikey + 1.45.0 + + + + + cn.dev33 + sa-token-sign + 1.45.0 + + + + + cn.dev33 + sa-token-quick-login + 1.45.0 + + + + + cn.dev33 + sa-token-sso + 1.45.0 + + + + + cn.dev33 + sa-token-spring-aop + 1.45.0 + + + + + cn.dev33 + sa-token-spring-el + 1.45.0 + + + + + cn.dev33 + sa-token-spring-boot-webmvc-reactor-v2v3v4-common + 1.45.0 + + + + + cn.dev33 + sa-token-spring-boot-reactor-v2v3v4-common + 1.45.0 + + + + + cn.dev33 + sa-token-spring-boot-webmvc-v3v4-common + 1.45.0 + diff --git a/sa-token-demo/pom.xml b/sa-token-demo/pom.xml index 21460ce7..8dd665a5 100644 --- a/sa-token-demo/pom.xml +++ b/sa-token-demo/pom.xml @@ -11,6 +11,7 @@ sa-token-demo-alone-redis sa-token-demo-alone-redis-cluster + sa-token-demo-alone-redis-sb4 sa-token-demo-apikey sa-token-demo-async sa-token-demo-beetl diff --git a/sa-token-demo/sa-token-demo-alone-redis-sb4/pom.xml b/sa-token-demo/sa-token-demo-alone-redis-sb4/pom.xml new file mode 100644 index 00000000..e157da08 --- /dev/null +++ b/sa-token-demo/sa-token-demo-alone-redis-sb4/pom.xml @@ -0,0 +1,78 @@ + + 4.0.0 + cn.dev33 + sa-token-demo-alone-redis-sb4 + 0.0.1-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-parent + 4.0.3 + + + + + + 1.45.0 + + + + + + + org.springframework.boot + spring-boot-starter-webmvc + + + org.springframework.boot + spring-boot-starter-aspectj + + + + + cn.dev33 + sa-token-spring-boot4-starter + ${sa-token.version} + + + + + cn.dev33 + sa-token-redis-template + ${sa-token.version} + + + + + cn.dev33 + sa-token-redis-template-jdk-serializer + ${sa-token.version} + test + + + + + org.apache.commons + commons-pool2 + + + + + cn.dev33 + sa-token-alone-redis-by-spring-boot4 + ${sa-token.version} + + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + diff --git a/sa-token-demo/sa-token-demo-alone-redis-sb4/src/main/java/com/pj/SaTokenAloneRedisSb4Application.java b/sa-token-demo/sa-token-demo-alone-redis-sb4/src/main/java/com/pj/SaTokenAloneRedisSb4Application.java new file mode 100644 index 00000000..eedf1503 --- /dev/null +++ b/sa-token-demo/sa-token-demo-alone-redis-sb4/src/main/java/com/pj/SaTokenAloneRedisSb4Application.java @@ -0,0 +1,20 @@ +package com.pj; + +import cn.dev33.satoken.SaManager; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Sa-Token 整合 SpringBoot4 示例,整合 alone-redis 插件(权限缓存与业务缓存分离) + * + * @author click33 + */ +@SpringBootApplication +public class SaTokenAloneRedisSb4Application { + + public static void main(String[] args) { + SpringApplication.run(SaTokenAloneRedisSb4Application.class, args); + System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig()); + } + +} diff --git a/sa-token-demo/sa-token-demo-alone-redis-sb4/src/main/java/com/pj/test/TestController.java b/sa-token-demo/sa-token-demo-alone-redis-sb4/src/main/java/com/pj/test/TestController.java new file mode 100644 index 00000000..240cd2eb --- /dev/null +++ b/sa-token-demo/sa-token-demo-alone-redis-sb4/src/main/java/com/pj/test/TestController.java @@ -0,0 +1,40 @@ +package com.pj.test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaResult; + +/** + * 测试专用Controller,演示 alone-redis 权限缓存与业务缓存分离 + * + * @author click33 + */ +@RestController +@RequestMapping("/test/") +public class TestController { + + @Autowired + StringRedisTemplate stringRedisTemplate; + + // 测试Sa-Token缓存,浏览器访问: http://localhost:8083/test/login + @RequestMapping("login") + public SaResult login(@RequestParam(defaultValue = "10001") String id) { + System.out.println("--------------- 测试Sa-Token缓存"); + StpUtil.login(id); + return SaResult.ok(); + } + + // 测试业务缓存,浏览器访问: http://localhost:8083/test/test + @RequestMapping("test") + public SaResult test() { + System.out.println("--------------- 测试业务缓存"); + stringRedisTemplate.opsForValue().set("hello", "Hello World"); + return SaResult.ok(); + } + +} diff --git a/sa-token-demo/sa-token-demo-alone-redis-sb4/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-alone-redis-sb4/src/main/resources/application.yml new file mode 100644 index 00000000..d700d19d --- /dev/null +++ b/sa-token-demo/sa-token-demo-alone-redis-sb4/src/main/resources/application.yml @@ -0,0 +1,59 @@ +# 端口 +server: + port: 8083 + +# Sa-Token配置 +sa-token: + # Token名称 (同时也是cookie名称) + token-name: satoken + # Token有效期,单位s 默认30天, -1代表永不过期 + timeout: 2592000 + # Token风格 + token-style: uuid + # 配置Sa-Token单独使用的Redis连接 + alone-redis: + # Redis数据库索引(默认为0) + database: 2 + # 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 + +# 配置业务使用的Redis连接 +spring: + data: + 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 diff --git a/sa-token-doc/plugin/alone-redis.md b/sa-token-doc/plugin/alone-redis.md index 1de2f524..b0c3b4b7 100644 --- a/sa-token-doc/plugin/alone-redis.md +++ b/sa-token-doc/plugin/alone-redis.md @@ -16,6 +16,12 @@ Sa-Token默认的Redis集成方式会把权限数据和业务缓存放在一起 ### 1、首先引入Alone-Redis依赖 + +!-- +> [!NOTE| label:Spring Boot 4 用户] +> 若使用 Spring Boot 4.x,请引入 `sa-token-alone-redis-by-spring-boot4` 替代 `sa-token-alone-redis`。 +--> + ``` xml diff --git a/sa-token-plugin/pom.xml b/sa-token-plugin/pom.xml index 16be841c..b18a6628 100644 --- a/sa-token-plugin/pom.xml +++ b/sa-token-plugin/pom.xml @@ -48,6 +48,7 @@ sa-token-redis-template-jdk-serializer sa-token-redis-jackson sa-token-alone-redis + sa-token-alone-redis-by-spring-boot4 sa-token-spring-aop sa-token-spring-el sa-token-grpc diff --git a/sa-token-plugin/sa-token-alone-redis-by-spring-boot4/pom.xml b/sa-token-plugin/sa-token-alone-redis-by-spring-boot4/pom.xml new file mode 100644 index 00000000..1c237768 --- /dev/null +++ b/sa-token-plugin/sa-token-alone-redis-by-spring-boot4/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + + cn.dev33 + sa-token-plugin + ${revision} + ../pom.xml + + jar + + sa-token-alone-redis-by-spring-boot4 + sa-token-alone-redis-by-spring-boot4 + sa-token-alone-redis for Spring Boot 4 + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + cn.dev33 + sa-token-redis-template + true + + + cn.dev33 + sa-token-redis-template-jdk-serializer + true + + + + org.apache.commons + commons-pool2 + true + + + + + + + cn.dev33 + sa-token-spring-boot4-dependencies + ${revision} + pom + import + + + + + diff --git a/sa-token-plugin/sa-token-alone-redis-by-spring-boot4/src/main/java/cn/dev33/satoken/dao/alone/SaAloneRedisInject.java b/sa-token-plugin/sa-token-alone-redis-by-spring-boot4/src/main/java/cn/dev33/satoken/dao/alone/SaAloneRedisInject.java new file mode 100644 index 00000000..d6590824 --- /dev/null +++ b/sa-token-plugin/sa-token-alone-redis-by-spring-boot4/src/main/java/cn/dev33/satoken/dao/alone/SaAloneRedisInject.java @@ -0,0 +1,228 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 cn.dev33.satoken.dao.alone; + +import cn.dev33.satoken.dao.SaTokenDao; +import cn.dev33.satoken.dao.SaTokenDaoDefaultImpl; +import cn.dev33.satoken.dao.SaTokenDaoForRedisTemplate; +import cn.dev33.satoken.exception.SaTokenException; +import jakarta.annotation.PostConstruct; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.boot.data.redis.autoconfigure.DataRedisProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.data.redis.connection.*; +import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 为 SaToken 单独设置 Redis 连接信息,使权限缓存与业务缓存分离 (springboot4 版本专用) + * + *

+ * 使用方式:在引入 sa-token redis 集成相关包的前提下,继续引入当前依赖

+ * 注意事项:目前本依赖仅对以下插件有 Redis 分离效果:
+ * sa-token-redis-template
+ * sa-token-redis-template-jdk-serializer
+ *

+ * + * + * @author click33 + * @since 1.21.0 + */ +@Configuration +public class SaAloneRedisInject { + + /** + * 配置信息的前缀 + */ + public static final String ALONE_PREFIX = "sa-token.alone-redis"; + + /** + * Sa-Token 持久层接口 + */ + private final SaTokenDao saTokenDao; + private final Environment environment; + + public SaAloneRedisInject(SaTokenDao saTokenDao, Environment environment) { + this.saTokenDao = saTokenDao; + this.environment = environment; + } + + /** + * 开始注入 + */ + @PostConstruct + public void init() { + try { + // 如果 saTokenDao 为空或者为默认实现,则不进行任何操作 + if(saTokenDao == null || saTokenDao instanceof SaTokenDaoDefaultImpl) { + return; + } + + // ------------------- 开始注入 + + // 获取cfg对象,解析开发者配置的 sa-token.alone-redis 相关信息 + DataRedisProperties cfg = Binder.get(environment).bind(ALONE_PREFIX, DataRedisProperties.class).get(); + + // 1. Redis配置 + RedisConfiguration redisAloneConfig; + String pattern = environment.getProperty(ALONE_PREFIX + ".pattern", "single"); + if (pattern.equals("single")) { + // 单体模式 + RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration(); + redisConfig.setHostName(cfg.getHost()); + redisConfig.setPort(cfg.getPort()); + redisConfig.setDatabase(cfg.getDatabase()); + redisConfig.setPassword(RedisPassword.of(cfg.getPassword())); + redisConfig.setUsername(cfg.getUsername()); + redisAloneConfig = redisConfig; + + } else if (pattern.equals("cluster")){ + // 普通集群模式 + RedisClusterConfiguration redisClusterConfig = new RedisClusterConfiguration(); + redisClusterConfig.setUsername(cfg.getUsername()); + redisClusterConfig.setPassword(RedisPassword.of(cfg.getPassword())); + + DataRedisProperties.Cluster cluster = cfg.getCluster(); + if (cluster == null || cluster.getNodes() == null) { + throw new SaTokenException("Alone-Redis 集群模式需要配置 cluster.nodes"); + } + List serverList = cluster.getNodes().stream().map(node -> { + String[] ipAndPort = node.split(":"); + return new RedisNode(ipAndPort[0].trim(), Integer.parseInt(ipAndPort[1])); + }).collect(Collectors.toList()); + redisClusterConfig.setClusterNodes(serverList); + if (cluster.getMaxRedirects() != null) { + redisClusterConfig.setMaxRedirects(cluster.getMaxRedirects()); + } + redisAloneConfig = redisClusterConfig; + } else if (pattern.equals("sentinel")) { + // 哨兵集群模式 + RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration(); + redisSentinelConfiguration.setDatabase(cfg.getDatabase()); + redisSentinelConfiguration.setUsername(cfg.getUsername()); + redisSentinelConfiguration.setPassword(RedisPassword.of(cfg.getPassword())); + + DataRedisProperties.Sentinel sentinel = cfg.getSentinel(); + if (sentinel == null || sentinel.getNodes() == null) { + throw new SaTokenException("Alone-Redis 哨兵模式需要配置 sentinel.nodes"); + } + redisSentinelConfiguration.setMaster(sentinel.getMaster()); + redisSentinelConfiguration.setSentinelPassword(sentinel.getPassword()); + List serverList = sentinel.getNodes().stream().map(node -> { + String[] ipAndPort = node.split(":"); + return new RedisNode(ipAndPort[0].trim(), Integer.parseInt(ipAndPort[1])); + }).collect(Collectors.toList()); + redisSentinelConfiguration.setSentinels(serverList); + + redisAloneConfig = redisSentinelConfiguration; + } else if (pattern.equals("socket")) { + // socket 连接单体 Redis + RedisSocketConfiguration redisSocketConfiguration = new RedisSocketConfiguration(); + redisSocketConfiguration.setDatabase(cfg.getDatabase()); + redisSocketConfiguration.setUsername(cfg.getUsername()); + redisSocketConfiguration.setPassword(RedisPassword.of(cfg.getPassword())); + String socket = environment.getProperty(ALONE_PREFIX + ".socket", ""); + redisSocketConfiguration.setSocket(socket); + + redisAloneConfig = redisSocketConfiguration; + } else if (pattern.equals("aws")) { + // AWS ElastiCache + // AWS Redis 远程主机地址: String hoseName = "****.***.****.****.cache.amazonaws.com"; + String hostName = cfg.getHost(); + int port = cfg.getPort(); + RedisStaticMasterReplicaConfiguration redisStaticMasterReplicaConfiguration = new RedisStaticMasterReplicaConfiguration(hostName, port); + redisStaticMasterReplicaConfiguration.setDatabase(cfg.getDatabase()); + redisStaticMasterReplicaConfiguration.setUsername(cfg.getUsername()); + redisStaticMasterReplicaConfiguration.setPassword(RedisPassword.of(cfg.getPassword())); + + redisAloneConfig = redisStaticMasterReplicaConfiguration; + } else { + // 模式无法识别 + throw new SaTokenException("SaToken 无法识别 Alone-Redis 配置的模式: " + pattern); + } + + // 2. 连接池配置 + GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); + // pool配置 + DataRedisProperties.Lettuce lettuce = cfg.getLettuce(); + if(lettuce.getPool() != null) { + DataRedisProperties.Pool pool = cfg.getLettuce().getPool(); + // 连接池最大连接数 + poolConfig.setMaxTotal(pool.getMaxActive()); + // 连接池中的最大空闲连接 + poolConfig.setMaxIdle(pool.getMaxIdle()); + // 连接池中的最小空闲连接 + poolConfig.setMinIdle(pool.getMinIdle()); + // 连接池最大阻塞等待时间(使用负值表示没有限制) + poolConfig.setMaxWaitMillis(pool.getMaxWait().toMillis()); + } + LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder(); + // timeout + if(cfg.getTimeout() != null) { + builder.commandTimeout(cfg.getTimeout()); + } + // shutdownTimeout + builder.shutdownTimeout(lettuce.getShutdownTimeout()); + // 创建Factory对象 + LettuceClientConfiguration clientConfig = builder.poolConfig(poolConfig).build(); + LettuceConnectionFactory factory = new LettuceConnectionFactory(redisAloneConfig, clientConfig); + factory.afterPropertiesSet(); + + // 3. 开始初始化 SaTokenDao ,此处需要依次判断开发者引入的是哪个 redis 库 + + // 如果开发者引入的是:sa-token-redis-template-jdk-serializer 或 sa-token-redis-template + try { + Class.forName("cn.dev33.satoken.dao.SaTokenDaoForRedisTemplateUseJdkSerializer"); + SaTokenDaoForRedisTemplate dao = (SaTokenDaoForRedisTemplate) saTokenDao; + dao.isInit = false; + dao.init(factory); + return; + } catch (ClassNotFoundException ignored) { + } + try { + Class.forName("cn.dev33.satoken.dao.SaTokenDaoForRedisTemplate"); + SaTokenDaoForRedisTemplate dao = (SaTokenDaoForRedisTemplate) saTokenDao; + dao.isInit = false; + dao.init(factory); + return; + } catch (ClassNotFoundException ignored) { + } + + // 至此,说明开发者一个 redis 插件也没引入,或者引入的 redis 插件不在 sa-token-alone-redis 的支持范围内 + throw new SaTokenException("未引入 sa-token-redis-xxx 相关插件,或引入的插件不在 Alone-Redis 支持范围内"); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 骗过编辑器,增加配置文件代码提示 + * @return 配置对象 + */ + @ConfigurationProperties(prefix = ALONE_PREFIX) + public DataRedisProperties getSaAloneRedisConfig() { + return new DataRedisProperties(); + } + +} diff --git a/sa-token-plugin/sa-token-alone-redis-by-spring-boot4/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/sa-token-plugin/sa-token-alone-redis-by-spring-boot4/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..74cac595 --- /dev/null +++ b/sa-token-plugin/sa-token-alone-redis-by-spring-boot4/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.dev33.satoken.dao.alone.SaAloneRedisInject diff --git a/sa-token-special-dependencies/sa-token-spring-boot4-dependencies/pom.xml b/sa-token-special-dependencies/sa-token-spring-boot4-dependencies/pom.xml index 767a5335..de9e494a 100644 --- a/sa-token-special-dependencies/sa-token-spring-boot4-dependencies/pom.xml +++ b/sa-token-special-dependencies/sa-token-spring-boot4-dependencies/pom.xml @@ -56,6 +56,21 @@ ${springboot4.version} + + + org.springframework.boot + spring-boot-starter-data-redis + ${springboot4.version} + + + + + org.apache.commons + commons-pool2 + 2.12.1 + true + +