diff --git a/pom.xml b/pom.xml index dddeac86c..064cd6ad1 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ 3.9.1 5.8.40 3.5.5 - 3.52.0 + 4.0.0 2.2.7 4.3.1 1.8.0 @@ -261,6 +261,17 @@ org.redisson redisson-spring-boot-starter ${redisson.version} + + + org.redisson + redisson-spring-data-40 + + + + + org.redisson + redisson-spring-data-35 + ${redisson.version} diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 1b52fab96..30884eeeb 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -107,29 +107,28 @@ spring.data: timeout: 10s # 是否开启ssl ssl.enabled: false - -# redisson 配置 -redisson: - # redis key前缀 - keyPrefix: - # 线程池数量 - threads: 4 - # Netty线程池数量 - nettyThreads: 8 - # 单节点配置 - singleServerConfig: - # 客户端名称 不能用中文 - clientName: RuoYi-Vue-Plus - # 最小空闲连接数 - connectionMinimumIdleSize: 8 - # 连接池大小 - connectionPoolSize: 32 - # 连接空闲超时,单位:毫秒 - idleConnectionTimeout: 10000 - # 命令等待超时,单位:毫秒 - timeout: 3000 - # 发布和订阅连接池大小 - subscriptionConnectionPoolSize: 50 + # redisson 配置 官方文档:https://redisson.pro/docs/integration-with-spring/#spring-boot-starter + redisson: + # redis key前缀 + keyPrefix: + # 线程池数量 + threads: 4 + # Netty线程池数量 + nettyThreads: 8 + # 单节点配置 + singleServerConfig: + # 客户端名称 不能用中文 + clientName: RuoYi-Vue-Plus + # 最小空闲连接数 + connectionMinimumIdleSize: 8 + # 连接池大小 + connectionPoolSize: 32 + # 连接空闲超时,单位:毫秒 + idleConnectionTimeout: 10000 + # 命令等待超时,单位:毫秒 + timeout: 3000 + # 发布和订阅连接池大小 + subscriptionConnectionPoolSize: 50 --- # mail 邮件发送 mail: diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index d77ddf57c..057936d5c 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -110,29 +110,28 @@ spring.data: timeout: 10s # 是否开启ssl ssl.enabled: false - -# redisson 配置 -redisson: - # redis key前缀 - keyPrefix: - # 线程池数量 - threads: 16 - # Netty线程池数量 - nettyThreads: 32 - # 单节点配置 - singleServerConfig: - # 客户端名称 不能用中文 - clientName: RuoYi-Vue-Plus - # 最小空闲连接数 - connectionMinimumIdleSize: 32 - # 连接池大小 - connectionPoolSize: 64 - # 连接空闲超时,单位:毫秒 - idleConnectionTimeout: 10000 - # 命令等待超时,单位:毫秒 - timeout: 3000 - # 发布和订阅连接池大小 - subscriptionConnectionPoolSize: 50 + # redisson 配置 官方文档:https://redisson.pro/docs/integration-with-spring/#spring-boot-starter + redisson: + # redis key前缀 + keyPrefix: + # 线程池数量 + threads: 16 + # Netty线程池数量 + nettyThreads: 32 + # 单节点配置 + singleServerConfig: + # 客户端名称 不能用中文 + clientName: RuoYi-Vue-Plus + # 最小空闲连接数 + connectionMinimumIdleSize: 32 + # 连接池大小 + connectionPoolSize: 64 + # 连接空闲超时,单位:毫秒 + idleConnectionTimeout: 10000 + # 命令等待超时,单位:毫秒 + timeout: 3000 + # 发布和订阅连接池大小 + subscriptionConnectionPoolSize: 50 --- # mail 邮件发送 mail: diff --git a/ruoyi-common/ruoyi-common-redis/pom.xml b/ruoyi-common/ruoyi-common-redis/pom.xml index 576be5e14..b961863b9 100644 --- a/ruoyi-common/ruoyi-common-redis/pom.xml +++ b/ruoyi-common/ruoyi-common-redis/pom.xml @@ -27,6 +27,10 @@ org.redisson redisson-spring-boot-starter + + org.redisson + redisson-spring-data-35 + com.baomidou diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java index 4c39196e8..1cf6142f2 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java @@ -1,6 +1,5 @@ package org.dromara.common.redis.config; -import cn.hutool.core.util.ObjectUtil; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; @@ -10,16 +9,14 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.redis.config.properties.RedissonProperties; import org.dromara.common.redis.handler.KeyPrefixHandler; import org.dromara.common.redis.handler.RedisExceptionHandler; import org.redisson.client.codec.StringCodec; import org.redisson.codec.CompositeCodec; import org.redisson.codec.TypedJsonJacksonCodec; import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.core.task.VirtualThreadTaskExecutor; @@ -34,11 +31,13 @@ import java.util.TimeZone; */ @Slf4j @AutoConfiguration -@EnableConfigurationProperties(RedissonProperties.class) public class RedisConfig { - @Autowired - private RedissonProperties redissonProperties; + /** + * redis缓存key前缀 + */ + @Value("${spring.data.redis.redisson.keyPrefix}") + private String keyPrefix; @Bean public RedissonAutoConfigurationCustomizer redissonCustomizer() { @@ -60,44 +59,11 @@ public class RedisConfig { TypedJsonJacksonCodec jsonCodec = new TypedJsonJacksonCodec(Object.class, om); // 组合序列化 key 使用 String 内容使用通用 json 格式 CompositeCodec codec = new CompositeCodec(StringCodec.INSTANCE, jsonCodec, jsonCodec); - config.setThreads(redissonProperties.getThreads()) - .setNettyThreads(redissonProperties.getNettyThreads()) - // 缓存 Lua 脚本 减少网络传输(redisson 大部分的功能都是基于 Lua 脚本实现) - .setUseScriptCache(true) - .setCodec(codec); + config.setCodec(codec); if (SpringUtils.isVirtual()) { config.setNettyExecutor(new VirtualThreadTaskExecutor("redisson-")); } - RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig(); - if (ObjectUtil.isNotNull(singleServerConfig)) { - // 使用单机模式 - config.useSingleServer() - //设置redis key前缀 - .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())) - .setTimeout(singleServerConfig.getTimeout()) - .setClientName(singleServerConfig.getClientName()) - .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout()) - .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize()) - .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize()) - .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize()); - } - // 集群配置方式 参考下方注释 - RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig(); - if (ObjectUtil.isNotNull(clusterServersConfig)) { - config.useClusterServers() - //设置redis key前缀 - .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())) - .setTimeout(clusterServersConfig.getTimeout()) - .setClientName(clusterServersConfig.getClientName()) - .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout()) - .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize()) - .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize()) - .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize()) - .setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize()) - .setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize()) - .setReadMode(clusterServersConfig.getReadMode()) - .setSubscriptionMode(clusterServersConfig.getSubscriptionMode()); - } + config.setNameMapper(new KeyPrefixHandler(keyPrefix)); log.info("初始化 redis 配置"); }; } @@ -127,34 +93,34 @@ public class RedisConfig { * timeout: 10s * # 是否开启ssl * ssl.enabled: false - * - * redisson: - * # 线程池数量 - * threads: 16 - * # Netty线程池数量 - * nettyThreads: 32 - * # 集群配置 - * clusterServersConfig: - * # 客户端名称 - * clientName: ${ruoyi.name} - * # master最小空闲连接数 - * masterConnectionMinimumIdleSize: 32 - * # master连接池大小 - * masterConnectionPoolSize: 64 - * # slave最小空闲连接数 - * slaveConnectionMinimumIdleSize: 32 - * # slave连接池大小 - * slaveConnectionPoolSize: 64 - * # 连接空闲超时,单位:毫秒 - * idleConnectionTimeout: 10000 - * # 命令等待超时,单位:毫秒 - * timeout: 3000 - * # 发布和订阅连接池大小 - * subscriptionConnectionPoolSize: 50 - * # 读取模式 - * readMode: "SLAVE" - * # 订阅模式 - * subscriptionMode: "MASTER" + * # redisson配置 + * redisson: + * # 线程池数量 + * threads: 16 + * # Netty线程池数量 + * nettyThreads: 32 + * # 集群配置 + * clusterServersConfig: + * # 客户端名称 + * clientName: ${ruoyi.name} + * # master最小空闲连接数 + * masterConnectionMinimumIdleSize: 32 + * # master连接池大小 + * masterConnectionPoolSize: 64 + * # slave最小空闲连接数 + * slaveConnectionMinimumIdleSize: 32 + * # slave连接池大小 + * slaveConnectionPoolSize: 64 + * # 连接空闲超时,单位:毫秒 + * idleConnectionTimeout: 10000 + * # 命令等待超时,单位:毫秒 + * timeout: 3000 + * # 发布和订阅连接池大小 + * subscriptionConnectionPoolSize: 50 + * # 读取模式 + * readMode: "SLAVE" + * # 订阅模式 + * subscriptionMode: "MASTER" */ } diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/properties/RedissonProperties.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/properties/RedissonProperties.java deleted file mode 100644 index ebec7861a..000000000 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/properties/RedissonProperties.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.dromara.common.redis.config.properties; - -import lombok.Data; -import lombok.NoArgsConstructor; -import org.redisson.config.ReadMode; -import org.redisson.config.SubscriptionMode; -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * Redisson 配置属性 - * - * @author Lion Li - */ -@Data -@ConfigurationProperties(prefix = "redisson") -public class RedissonProperties { - - /** - * redis缓存key前缀 - */ - private String keyPrefix; - - /** - * 线程池数量,默认值 = 当前处理核数量 * 2 - */ - private int threads; - - /** - * Netty线程池数量,默认值 = 当前处理核数量 * 2 - */ - private int nettyThreads; - - /** - * 单机服务配置 - */ - private SingleServerConfig singleServerConfig; - - /** - * 集群服务配置 - */ - private ClusterServersConfig clusterServersConfig; - - @Data - @NoArgsConstructor - public static class SingleServerConfig { - - /** - * 客户端名称 - */ - private String clientName; - - /** - * 最小空闲连接数 - */ - private int connectionMinimumIdleSize; - - /** - * 连接池大小 - */ - private int connectionPoolSize; - - /** - * 连接空闲超时,单位:毫秒 - */ - private int idleConnectionTimeout; - - /** - * 命令等待超时,单位:毫秒 - */ - private int timeout; - - /** - * 发布和订阅连接池大小 - */ - private int subscriptionConnectionPoolSize; - - } - - @Data - @NoArgsConstructor - public static class ClusterServersConfig { - - /** - * 客户端名称 - */ - private String clientName; - - /** - * master最小空闲连接数 - */ - private int masterConnectionMinimumIdleSize; - - /** - * master连接池大小 - */ - private int masterConnectionPoolSize; - - /** - * slave最小空闲连接数 - */ - private int slaveConnectionMinimumIdleSize; - - /** - * slave连接池大小 - */ - private int slaveConnectionPoolSize; - - /** - * 连接空闲超时,单位:毫秒 - */ - private int idleConnectionTimeout; - - /** - * 命令等待超时,单位:毫秒 - */ - private int timeout; - - /** - * 发布和订阅连接池大小 - */ - private int subscriptionConnectionPoolSize; - - /** - * 读取模式 - */ - private ReadMode readMode; - - /** - * 订阅模式 - */ - private SubscriptionMode subscriptionMode; - - } - -} diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/handler/KeyPrefixHandler.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/handler/KeyPrefixHandler.java index 3bf3e346a..33d5cde82 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/handler/KeyPrefixHandler.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/handler/KeyPrefixHandler.java @@ -1,7 +1,7 @@ package org.dromara.common.redis.handler; import org.dromara.common.core.utils.StringUtils; -import org.redisson.api.NameMapper; +import org.redisson.config.NameMapper; /** * redis缓存key前缀处理 @@ -24,9 +24,6 @@ public class KeyPrefixHandler implements NameMapper { */ @Override public String map(String name) { - if (StringUtils.isBlank(name)) { - return null; - } if (StringUtils.isNotBlank(keyPrefix) && !name.startsWith(keyPrefix)) { return keyPrefix + name; } @@ -38,9 +35,6 @@ public class KeyPrefixHandler implements NameMapper { */ @Override public String unmap(String name) { - if (StringUtils.isBlank(name)) { - return null; - } if (StringUtils.isNotBlank(keyPrefix) && name.startsWith(keyPrefix)) { return name.substring(keyPrefix.length()); } diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java index 3767fa2f1..9f25ecfbe 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java @@ -1,18 +1,14 @@ package org.dromara.common.tenant.config; import cn.dev33.satoken.dao.SaTokenDao; -import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; -import org.dromara.common.core.utils.reflect.ReflectUtils; import org.dromara.common.redis.config.RedisConfig; -import org.dromara.common.redis.config.properties.RedissonProperties; +import org.dromara.common.redis.handler.KeyPrefixHandler; import org.dromara.common.tenant.core.TenantSaTokenDao; import org.dromara.common.tenant.handle.PlusTenantLineHandler; import org.dromara.common.tenant.handle.TenantKeyPrefixHandler; import org.dromara.common.tenant.manager.TenantSpringCacheManager; import org.dromara.common.tenant.properties.TenantProperties; -import org.redisson.config.ClusterServersConfig; -import org.redisson.config.SingleServerConfig; import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -47,20 +43,11 @@ public class TenantConfig { } @Bean - public RedissonAutoConfigurationCustomizer tenantRedissonCustomizer(RedissonProperties redissonProperties) { + public RedissonAutoConfigurationCustomizer tenantRedissonCustomizer() { return config -> { - TenantKeyPrefixHandler nameMapper = new TenantKeyPrefixHandler(redissonProperties.getKeyPrefix()); - SingleServerConfig singleServerConfig = ReflectUtils.invokeGetter(config, "singleServerConfig"); - if (ObjectUtil.isNotNull(singleServerConfig)) { - // 使用单机模式 - // 设置多租户 redis key前缀 - singleServerConfig.setNameMapper(nameMapper); - } - ClusterServersConfig clusterServersConfig = ReflectUtils.invokeGetter(config, "clusterServersConfig"); - // 集群配置方式 参考下方注释 - if (ObjectUtil.isNotNull(clusterServersConfig)) { - // 设置多租户 redis key前缀 - clusterServersConfig.setNameMapper(nameMapper); + if (config.getNameMapper() instanceof KeyPrefixHandler handler) { + // 使用多租户redis缓存key前缀处理器 + config.setNameMapper(new TenantKeyPrefixHandler(handler)); } }; } diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java index dcdef6e62..bcac4675c 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java @@ -6,6 +6,7 @@ import org.dromara.common.core.constant.GlobalConstants; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.redis.handler.KeyPrefixHandler; import org.dromara.common.tenant.helper.TenantHelper; +import org.redisson.config.NameMapper; /** * 多租户redis缓存key前缀处理 @@ -13,10 +14,15 @@ import org.dromara.common.tenant.helper.TenantHelper; * @author Lion Li */ @Slf4j -public class TenantKeyPrefixHandler extends KeyPrefixHandler { +public class TenantKeyPrefixHandler implements NameMapper { - public TenantKeyPrefixHandler(String keyPrefix) { - super(keyPrefix); + /** + * Key前缀处理器 + */ + private final KeyPrefixHandler handler; + + public TenantKeyPrefixHandler(KeyPrefixHandler handler) { + this.handler = handler; } /** @@ -25,28 +31,24 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler { @Override public String map(String name) { if (StringUtils.isBlank(name)) { - return null; + return name; } - try { - if (InterceptorIgnoreHelper.willIgnoreTenantLine("")) { - return super.map(name); - } - } catch (NoClassDefFoundError ignore) { - // 有些服务不需要mp导致类不存在 忽略即可 - } - if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { - return super.map(name); + // 租户忽略和全局键检查 + if (shouldSkipTenantProcessing() || StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { + return handler.map(name); } + // 拼接租户前缀 String tenantId = TenantHelper.getTenantId(); if (StringUtils.isBlank(tenantId)) { log.debug("无法获取有效的租户id -> Null"); - return super.map(name); + return handler.map(name); } - if (StringUtils.startsWith(name, tenantId + "")) { + String tenantPrefix = tenantId + ":"; + if (StringUtils.startsWith(name, tenantPrefix)) { // 如果存在则直接返回 - return super.map(name); + return handler.map(name); } - return super.map(tenantId + ":" + name); + return handler.map(tenantPrefix + name); } /** @@ -54,30 +56,35 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler { */ @Override public String unmap(String name) { - String unmap = super.unmap(name); + String unmap = handler.unmap(name); if (StringUtils.isBlank(unmap)) { - return null; - } - try { - if (InterceptorIgnoreHelper.willIgnoreTenantLine("")) { - return unmap; - } - } catch (NoClassDefFoundError ignore) { - // 有些服务不需要mp导致类不存在 忽略即可 - } - if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { return unmap; } + // 租户忽略和全局键检查 + if (shouldSkipTenantProcessing() || StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { + return unmap; + } + // 拼接租户前缀 String tenantId = TenantHelper.getTenantId(); if (StringUtils.isBlank(tenantId)) { log.debug("无法获取有效的租户id -> Null"); return unmap; } - if (StringUtils.startsWith(unmap, tenantId + "")) { + String tenantPrefix = tenantId + ":"; + if (StringUtils.startsWith(unmap, tenantPrefix)) { // 如果存在则删除 - return unmap.substring((tenantId + ":").length()); + return unmap.substring(tenantPrefix.length()); } return unmap; } + private boolean shouldSkipTenantProcessing() { + try { + return InterceptorIgnoreHelper.willIgnoreTenantLine(""); + } catch (NoClassDefFoundError ignore) { + // 有些服务不需要mp导致类不存在 忽略即可 + return false; + } + } + }