diff --git a/pom.xml b/pom.xml
index 6bcf6522..ee9060ef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,6 +40,7 @@
3.2.2
2.12.2
5.7.16
+ 3.16.7
@@ -217,6 +218,13 @@
${hutool.version}
+
+
+ org.redisson
+ redisson-spring-boot-starter
+ ${redisson.version}
+
+
com.ruoyi
diff --git a/ruoyi-common/ruoyi-common-redis/pom.xml b/ruoyi-common/ruoyi-common-redis/pom.xml
index 754c4704..00fa74c1 100644
--- a/ruoyi-common/ruoyi-common-redis/pom.xml
+++ b/ruoyi-common/ruoyi-common-redis/pom.xml
@@ -22,6 +22,12 @@
org.springframework.boot
spring-boot-starter-data-redis
+
+
+
+ org.redisson
+ redisson-spring-boot-starter
+
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/RedisConfig.java b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/RedisConfig.java
new file mode 100644
index 00000000..2f1c008f
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/RedisConfig.java
@@ -0,0 +1,198 @@
+package com.ruoyi.common.redis.config;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.redis.config.properties.RedissonProperties;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.codec.JsonJacksonCodec;
+import org.redisson.config.Config;
+import org.redisson.spring.cache.CacheConfig;
+import org.redisson.spring.cache.RedissonSpringCacheManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * redis配置
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@Configuration
+@EnableCaching
+public class RedisConfig extends CachingConfigurerSupport {
+
+ private static final String REDIS_PROTOCOL_PREFIX = "redis://";
+ private static final String REDISS_PROTOCOL_PREFIX = "rediss://";
+
+ @Autowired
+ private RedisProperties redisProperties;
+
+ @Autowired
+ private RedissonProperties redissonProperties;
+
+ @Bean(destroyMethod = "shutdown")
+ @ConditionalOnMissingBean(RedissonClient.class)
+ public RedissonClient redisson() throws IOException {
+ String prefix = REDIS_PROTOCOL_PREFIX;
+ if (redisProperties.isSsl()) {
+ prefix = REDISS_PROTOCOL_PREFIX;
+ }
+ Config config = new Config();
+ config.setThreads(redissonProperties.getThreads())
+ .setNettyThreads(redissonProperties.getNettyThreads())
+ .setCodec(JsonJacksonCodec.INSTANCE)
+ .setTransportMode(redissonProperties.getTransportMode());
+
+ RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
+ if (ObjectUtil.isNotNull(singleServerConfig)) {
+ // 使用单机模式
+ config.useSingleServer()
+ .setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
+ .setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
+ .setDatabase(redisProperties.getDatabase())
+ .setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
+ .setTimeout(singleServerConfig.getTimeout())
+ .setRetryAttempts(singleServerConfig.getRetryAttempts())
+ .setRetryInterval(singleServerConfig.getRetryInterval())
+ .setSubscriptionsPerConnection(singleServerConfig.getSubscriptionsPerConnection())
+ .setClientName(singleServerConfig.getClientName())
+ .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
+ .setSubscriptionConnectionMinimumIdleSize(singleServerConfig.getSubscriptionConnectionMinimumIdleSize())
+ .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
+ .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
+ .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
+ .setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
+ }
+ // 集群配置方式 参考下方注释
+ RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();
+ if (ObjectUtil.isNotNull(clusterServersConfig)) {
+ // 使用集群模式
+ String finalPrefix = prefix;
+ List nodes = redisProperties.getCluster().getNodes()
+ .stream()
+ .map(node -> finalPrefix + node)
+ .collect(Collectors.toList());
+
+ config.useClusterServers()
+ .setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
+ .setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
+ .setTimeout(clusterServersConfig.getTimeout())
+ .setRetryAttempts(clusterServersConfig.getRetryAttempts())
+ .setRetryInterval(clusterServersConfig.getRetryInterval())
+ .setSubscriptionsPerConnection(clusterServersConfig.getSubscriptionsPerConnection())
+ .setClientName(clusterServersConfig.getClientName())
+ .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
+ .setPingConnectionInterval(clusterServersConfig.getPingConnectionInterval())
+ .setSubscriptionConnectionMinimumIdleSize(clusterServersConfig.getSubscriptionConnectionMinimumIdleSize())
+ .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
+ .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
+ .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
+ .setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
+ .setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
+ .setDnsMonitoringInterval(clusterServersConfig.getDnsMonitoringInterval())
+ .setFailedSlaveReconnectionInterval(clusterServersConfig.getFailedSlaveReconnectionInterval())
+ .setScanInterval(clusterServersConfig.getScanInterval())
+ .setReadMode(clusterServersConfig.getReadMode())
+ .setSubscriptionMode(clusterServersConfig.getSubscriptionMode())
+ .setNodeAddresses(nodes);
+ }
+ RedissonClient redissonClient = Redisson.create(config);
+ log.info("初始化 redis 配置");
+ return redissonClient;
+ }
+
+ /**
+ * 整合spring-cache
+ */
+ @Bean
+ public CacheManager cacheManager(RedissonClient redissonClient) {
+ List cacheGroup = redissonProperties.getCacheGroup();
+ Map config = new HashMap<>();
+ for (RedissonProperties.CacheGroup group : cacheGroup) {
+ CacheConfig cacheConfig = new CacheConfig(group.getTtl(), group.getMaxIdleTime());
+ cacheConfig.setMaxSize(group.getMaxSize());
+ config.put(group.getGroupId(), cacheConfig);
+ }
+ return new RedissonSpringCacheManager(redissonClient, config, JsonJacksonCodec.INSTANCE);
+ }
+
+ /**
+ * redis集群配置 yml
+ *
+ * --- # redis 集群配置(单机与集群只能开启一个另一个需要注释掉)
+ * spring:
+ * redis:
+ * cluster:
+ * nodes:
+ * - 192.168.0.100:6379
+ * - 192.168.0.101:6379
+ * - 192.168.0.102:6379
+ * # 密码
+ * password:
+ * # 连接超时时间
+ * timeout: 10s
+ * # 是否开启ssl
+ * ssl: false
+ *
+ * redisson:
+ * # 线程池数量
+ * threads: 16
+ * # Netty线程池数量
+ * nettyThreads: 32
+ * # 传输模式
+ * transportMode: "NIO"
+ * # 集群配置
+ * clusterServersConfig:
+ * # 客户端名称
+ * clientName: ${ruoyi.name}
+ * # master最小空闲连接数
+ * masterConnectionMinimumIdleSize: 32
+ * # master连接池大小
+ * masterConnectionPoolSize: 64
+ * # slave最小空闲连接数
+ * slaveConnectionMinimumIdleSize: 32
+ * # slave连接池大小
+ * slaveConnectionPoolSize: 64
+ * # 连接空闲超时,单位:毫秒
+ * idleConnectionTimeout: 10000
+ * # ping连接间隔
+ * pingConnectionInterval: 1000
+ * # 命令等待超时,单位:毫秒
+ * timeout: 3000
+ * # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
+ * retryAttempts: 3
+ * # 命令重试发送时间间隔,单位:毫秒
+ * retryInterval: 1500
+ * # 从可用服务器的内部列表中排除 Redis Slave 重新连接尝试的间隔。
+ * failedSlaveReconnectionInterval: 3000
+ * # 发布和订阅连接池最小空闲连接数
+ * subscriptionConnectionMinimumIdleSize: 1
+ * # 发布和订阅连接池大小
+ * subscriptionConnectionPoolSize: 50
+ * # 单个连接最大订阅数量
+ * subscriptionsPerConnection: 5
+ * # 扫描间隔
+ * scanInterval: 1000
+ * # DNS监测时间间隔,单位:毫秒
+ * dnsMonitoringInterval: 5000
+ * # 读取模式
+ * readMode: "SLAVE"
+ * # 订阅模式
+ * subscriptionMode: "MASTER"
+ */
+
+}
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/properties/RedissonProperties.java b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/properties/RedissonProperties.java
new file mode 100644
index 00000000..593de9ee
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/properties/RedissonProperties.java
@@ -0,0 +1,236 @@
+package com.ruoyi.common.redis.config.properties;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.redisson.config.ReadMode;
+import org.redisson.config.SubscriptionMode;
+import org.redisson.config.TransportMode;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * Redisson 配置属性
+ *
+ * @author Lion Li
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "redisson")
+public class RedissonProperties {
+
+ /**
+ * 线程池数量,默认值 = 当前处理核数量 * 2
+ */
+ private int threads;
+
+ /**
+ * Netty线程池数量,默认值 = 当前处理核数量 * 2
+ */
+ private int nettyThreads;
+
+ /**
+ * 传输模式
+ */
+ private TransportMode transportMode;
+
+ /**
+ * 单机服务配置
+ */
+ private SingleServerConfig singleServerConfig;
+
+ /**
+ * 集群服务配置
+ */
+ private ClusterServersConfig clusterServersConfig;
+
+ /**
+ * 缓存组
+ */
+ private List cacheGroup;
+
+ @Data
+ @NoArgsConstructor
+ public static class SingleServerConfig {
+
+ /**
+ * 客户端名称
+ */
+ private String clientName;
+
+ /**
+ * 最小空闲连接数
+ */
+ private int connectionMinimumIdleSize;
+
+ /**
+ * 连接池大小
+ */
+ private int connectionPoolSize;
+
+ /**
+ * 连接空闲超时,单位:毫秒
+ */
+ private int idleConnectionTimeout;
+
+ /**
+ * 命令等待超时,单位:毫秒
+ */
+ private int timeout;
+
+ /**
+ * 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
+ */
+ private int retryAttempts;
+
+ /**
+ * 命令重试发送时间间隔,单位:毫秒
+ */
+ private int retryInterval;
+
+ /**
+ * 发布和订阅连接的最小空闲连接数
+ */
+ private int subscriptionConnectionMinimumIdleSize;
+
+ /**
+ * 发布和订阅连接池大小
+ */
+ private int subscriptionConnectionPoolSize;
+
+ /**
+ * 单个连接最大订阅数量
+ */
+ private int subscriptionsPerConnection;
+
+ /**
+ * DNS监测时间间隔,单位:毫秒
+ */
+ private int dnsMonitoringInterval;
+
+ }
+
+ @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;
+
+ /**
+ * ping超时
+ */
+ private int pingConnectionInterval;
+
+ /**
+ * 命令等待超时,单位:毫秒
+ */
+ private int timeout;
+
+ /**
+ * 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
+ */
+ private int retryAttempts;
+
+ /**
+ * 命令重试发送时间间隔,单位:毫秒
+ */
+ private int retryInterval;
+
+ /**
+ * 错误重试次数
+ */
+ private int failedSlaveReconnectionInterval;
+
+ /**
+ * 发布和订阅连接池最小空闲连接数
+ */
+ private int subscriptionConnectionMinimumIdleSize;
+
+ /**
+ * 发布和订阅连接池大小
+ */
+ private int subscriptionConnectionPoolSize;
+
+ /**
+ * 单个连接最大订阅数量
+ */
+ private int subscriptionsPerConnection;
+
+ /**
+ * 扫描间隔
+ */
+ private int scanInterval;
+
+ /**
+ * DNS监测时间间隔,单位:毫秒
+ */
+ private int dnsMonitoringInterval;
+
+ /**
+ * 读取模式
+ */
+ private ReadMode readMode;
+
+ /**
+ * 订阅模式
+ */
+ private SubscriptionMode subscriptionMode;
+
+ }
+
+ @Data
+ @NoArgsConstructor
+ public static class CacheGroup {
+
+ /**
+ * 组id
+ */
+ private String groupId;
+
+ /**
+ * 组过期时间
+ */
+ private long ttl;
+
+ /**
+ * 组最大空闲时间
+ */
+ private long maxIdleTime;
+
+ /**
+ * 组最大长度
+ */
+ private int maxSize;
+
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/configure/FastJson2JsonRedisSerializer.java b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/configure/FastJson2JsonRedisSerializer.java
deleted file mode 100644
index 012eeb8e..00000000
--- a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/configure/FastJson2JsonRedisSerializer.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.ruoyi.common.redis.configure;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.serializer.SerializerFeature;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.type.TypeFactory;
-import org.springframework.data.redis.serializer.RedisSerializer;
-import org.springframework.data.redis.serializer.SerializationException;
-import com.alibaba.fastjson.parser.ParserConfig;
-import org.springframework.util.Assert;
-import java.nio.charset.Charset;
-
-/**
- * Redis使用FastJson序列化
- *
- * @author ruoyi
- */
-public class FastJson2JsonRedisSerializer implements RedisSerializer
-{
- @SuppressWarnings("unused")
- private ObjectMapper objectMapper = new ObjectMapper();
-
- public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
-
- private Class clazz;
-
- static
- {
- ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
- }
-
- public FastJson2JsonRedisSerializer(Class clazz)
- {
- super();
- this.clazz = clazz;
- }
-
- @Override
- public byte[] serialize(T t) throws SerializationException
- {
- if (t == null)
- {
- return new byte[0];
- }
- return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
- }
-
- @Override
- public T deserialize(byte[] bytes) throws SerializationException
- {
- if (bytes == null || bytes.length <= 0)
- {
- return null;
- }
- String str = new String(bytes, DEFAULT_CHARSET);
-
- return JSON.parseObject(str, clazz);
- }
-
- public void setObjectMapper(ObjectMapper objectMapper)
- {
- Assert.notNull(objectMapper, "'objectMapper' must not be null");
- this.objectMapper = objectMapper;
- }
-
- protected JavaType getJavaType(Class> clazz)
- {
- return TypeFactory.defaultInstance().constructType(clazz);
- }
-}
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/configure/RedisConfig.java b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/configure/RedisConfig.java
deleted file mode 100644
index 31238d63..00000000
--- a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/configure/RedisConfig.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.ruoyi.common.redis.configure;
-
-import org.springframework.cache.annotation.CachingConfigurerSupport;
-import org.springframework.cache.annotation.EnableCaching;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.data.redis.connection.RedisConnectionFactory;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.serializer.StringRedisSerializer;
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.annotation.PropertyAccessor;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
-
-/**
- * redis配置
- *
- * @author ruoyi
- */
-@Configuration
-@EnableCaching
-public class RedisConfig extends CachingConfigurerSupport
-{
- @Bean
- @SuppressWarnings(value = { "unchecked", "rawtypes" })
- public RedisTemplate