From c9260c49660137967a8f44485979829b9b0be38b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?=
<15040126243@163.com>
Date: Mon, 7 Feb 2022 15:13:15 +0000
Subject: [PATCH 1/5] update README.md.
---
README.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/README.md b/README.md
index 353e087fc..896d6c3ac 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,8 @@
+# 此分支进入维护阶段
+> 不进行更新 只修复bug 持续维护到2022年10月
+> 推荐使用 4.X 版本
+> 主分支与Sa-Token分支合并
+
## 平台简介
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
[](https://github.com/JavaLionLi/RuoYi-Vue-Plus)
From 82e8ab2385b8d0b5c4f11cbdcee42178896fe61f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90li?=
<15040126243@163.com>
Date: Fri, 18 Feb 2022 10:39:53 +0800
Subject: [PATCH 2/5] =?UTF-8?q?add=20=E5=A2=9E=E5=8A=A0=E9=A1=B5=E9=9D=A2?=
=?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AF=B4=E6=98=8E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 5 -----
1 file changed, 5 deletions(-)
diff --git a/README.md b/README.md
index 896d6c3ac..353e087fc 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,3 @@
-# 此分支进入维护阶段
-> 不进行更新 只修复bug 持续维护到2022年10月
-> 推荐使用 4.X 版本
-> 主分支与Sa-Token分支合并
-
## 平台简介
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
[](https://github.com/JavaLionLi/RuoYi-Vue-Plus)
From f3a4104fd061a8895fa5c44e6d9260b718d6311a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90li?=
<15040126243@163.com>
Date: Fri, 18 Feb 2022 14:05:32 +0800
Subject: [PATCH 3/5] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20minio=20?=
=?UTF-8?q?=E9=80=82=E9=85=8D=20https=20=E5=AF=BC=E8=87=B4=E7=9A=84?=
=?UTF-8?q?=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ruoyi/oss/service/impl/MinioOssStrategy.java | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/service/impl/MinioOssStrategy.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/service/impl/MinioOssStrategy.java
index eb2e77042..93f88fb3a 100644
--- a/ruoyi-oss/src/main/java/com/ruoyi/oss/service/impl/MinioOssStrategy.java
+++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/service/impl/MinioOssStrategy.java
@@ -9,6 +9,8 @@ import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.properties.OssProperties;
import com.ruoyi.oss.service.abstractd.AbstractOssStrategy;
import io.minio.*;
+import io.minio.http.HttpUtils;
+import okhttp3.HttpUrl;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
@@ -29,10 +31,15 @@ public class MinioOssStrategy extends AbstractOssStrategy {
public void init(OssProperties ossProperties) {
super.init(ossProperties);
try {
- minioClient = MinioClient.builder()
- .endpoint(properties.getEndpoint(), 443, OssConstant.IS_HTTPS.equals(ossProperties.getIsHttps()))
- .credentials(properties.getAccessKey(), properties.getSecretKey())
- .build();
+ MinioClient.Builder builder = MinioClient.builder();
+ if (OssConstant.IS_HTTPS.equals(ossProperties.getIsHttps())) {
+ HttpUrl url = HttpUtils.getBaseUrl(properties.getEndpoint())
+ .newBuilder().scheme("https").build();
+ builder.endpoint(url);
+ } else {
+ builder.endpoint(properties.getEndpoint());
+ }
+ minioClient = builder.credentials(properties.getAccessKey(), properties.getSecretKey()).build();
createBucket();
} catch (Exception e) {
throw new OssException("Minio存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
From 329c070e058b05e014c4f2d226098949e6df0a0d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?=
<15040126243@163.com>
Date: Fri, 18 Feb 2022 16:20:58 +0000
Subject: [PATCH 4/5] =?UTF-8?q?update=20=E6=9B=B4=E6=96=B0=20=E5=A4=9A?=
=?UTF-8?q?=E7=94=A8=E6=88=B7=E5=A4=9A=E8=AE=BE=E5=A4=87=E7=9A=84=E6=B3=A8?=
=?UTF-8?q?=E9=87=8A=E8=AF=B4=E6=98=8E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/com/ruoyi/common/helper/LoginHelper.java | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java
index a15220859..cd0d25cfd 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java
@@ -12,7 +12,13 @@ import lombok.NoArgsConstructor;
/**
* 登录鉴权助手
- * 为适配多端登录而封装
+ *
+ * user_type 为 用户类型 同一个用户表 可以有多种用户类型 例如 pc,app
+ * deivce 为 设备类型 同一个用户类型 可以有 多种设备类型 例如 web,ios
+ * 可以组成 用户类型与设备类型多对多的 权限灵活控制
+ *
+ * 多用户体系 针对 多种用户类型 但权限控制不一致
+ * 可以组成 多用户类型表与多设备类型 分别控制权限
*
* @author Lion Li
*/
@@ -26,7 +32,6 @@ public class LoginHelper {
/**
* 登录系统
- * 针对两套用户体系
*
* @param loginUser 登录用户信息
*/
@@ -38,7 +43,7 @@ public class LoginHelper {
/**
* 登录系统 基于 设备类型
- * 针对一套用户体系
+ * 针对相同用户体系不同设备
*
* @param loginUser 登录用户信息
*/
From 654180e677e1faa475112c7147b2f19f3dd8be25 Mon Sep 17 00:00:00 2001
From: yongen
Date: Tue, 22 Mar 2022 16:33:52 +0800
Subject: [PATCH 5/5] =?UTF-8?q?1:=20=E5=A2=9E=E5=8A=A0redis=E9=85=8D?=
=?UTF-8?q?=E7=BD=AE=E5=88=9D=E5=A7=8B=E5=8C=96=E6=8C=87=E5=AE=9Akey?=
=?UTF-8?q?=E5=89=8D=E7=BC=80=EF=BC=8C=E8=A7=A3=E5=86=B3=E5=A4=9A=E5=BA=94?=
=?UTF-8?q?=E7=94=A8=E5=85=B1=E7=94=A8=E4=B8=80=E4=B8=AAredis=E7=8E=AF?=
=?UTF-8?q?=E5=A2=83=E6=97=B6key=E8=A6=86=E7=9B=96=E7=9A=84=E9=97=AE?=
=?UTF-8?q?=E9=A2=98=E3=80=82=202:=20=E5=A2=9E=E5=8A=A0redis=E5=93=A8?=
=?UTF-8?q?=E5=85=B5=E9=85=8D=E7=BD=AE=E6=A8=A1=E5=BC=8F=EF=BC=8C=E4=BC=98?=
=?UTF-8?q?=E5=8C=96=E8=87=AA=E5=8A=A8=E9=85=8D=E7=BD=AE=E4=BB=A3=E7=A0=81?=
=?UTF-8?q?=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/resources/application-dev.yml | 39 ++-
.../ruoyi/framework/config/RedisConfig.java | 179 -----------
.../config/properties/RedissonProperties.java | 40 +++
.../config/redisson/KeyPrefixMapper.java | 42 +++
.../config/redisson/RedisConfig.java | 293 ++++++++++++++++++
5 files changed, 411 insertions(+), 182 deletions(-)
delete mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/redisson/KeyPrefixMapper.java
create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/redisson/RedisConfig.java
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index ba38be663..f881d8816 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -19,7 +19,7 @@ xxl:
# 执行器开关
enabled: true
# 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。
- admin-addresses: http://localhost:9100/xxl-job-admin
+ admin-addresses: http://127.0.0.1:9870/xxl-job-admin/
# 执行器通讯TOKEN:非空时启用
access-token: xxl-job
# 执行器配置
@@ -55,7 +55,7 @@ spring:
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username: root
- password: root
+ password: 12345678
# 从库数据源
slave:
lazy: true
@@ -121,7 +121,7 @@ spring:
# 数据库索引
database: 0
# 密码
- password:
+ password: 12345678
# 连接超时时间
timeout: 10s
# 是否开启ssl
@@ -134,6 +134,10 @@ redisson:
nettyThreads: 8
# 传输模式
transportMode: "NIO"
+ # 缓存前缀
+ key-prefix: ${ruoyi.name}
+ # 配置方式
+ mode: "SINGLE"
# 单节点配置
singleServerConfig:
# 客户端名称
@@ -152,3 +156,32 @@ redisson:
retryInterval: 1500
# 发布和订阅连接池大小
subscriptionConnectionPoolSize: 50
+ # 集群配置
+# 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
+# # 发布和订阅连接池大小
+# subscriptionConnectionPoolSize: 50
+# # 读取模式
+# readMode: "SLAVE"
+# # 订阅模式
+# subscriptionMode: "MASTER"
+
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
deleted file mode 100644
index a8bec417a..000000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package com.ruoyi.framework.config;
-
-import cn.hutool.core.util.ObjectUtil;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.framework.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.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 org.springframework.context.annotation.Primary;
-
-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;
-
- @Primary
- @Bean(destroyMethod = "shutdown")
- public RedissonClient redisson() {
- 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())
- .setClientName(singleServerConfig.getClientName())
- .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
- .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
- .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
- .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize());
- }
- // 集群配置方式 参考下方注释
- 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())
- .setClientName(clusterServersConfig.getClientName())
- .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
- .setPingConnectionInterval(clusterServersConfig.getPingConnectionInterval())
- .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
- .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
- .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
- .setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
- .setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
- .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
- * # 发布和订阅连接池大小
- * subscriptionConnectionPoolSize: 50
- * # 读取模式
- * readMode: "SLAVE"
- * # 订阅模式
- * subscriptionMode: "MASTER"
- */
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java
index eae9e3fc8..b06ac2a21 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java
@@ -1,6 +1,10 @@
package com.ruoyi.framework.config.properties;
+import com.ruoyi.common.core.domain.R;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.Getter;
import lombok.NoArgsConstructor;
import org.redisson.config.ReadMode;
import org.redisson.config.SubscriptionMode;
@@ -20,6 +24,15 @@ import java.util.List;
@ConfigurationProperties(prefix = "redisson")
public class RedissonProperties {
+
+ /**
+ * 连接模式
+ */
+ public static final String MODE_SINGLE = "SINGLE";
+ public static final String MODE_SENTINEL = "SENTINEL";
+ public static final String MODE_CLUSTER = "CLUSTER";
+
+
/**
* 线程池数量,默认值 = 当前处理核数量 * 2
*/
@@ -50,6 +63,16 @@ public class RedissonProperties {
*/
private List cacheGroup;
+ /**
+ * 缓存key前缀
+ */
+ private String keyPrefix;
+
+ /**
+ * 配置方式
+ */
+ private RedisMode mode;
+
@Data
@NoArgsConstructor
public static class SingleServerConfig {
@@ -193,4 +216,21 @@ public class RedissonProperties {
}
+ @AllArgsConstructor(access = AccessLevel.PRIVATE)
+ public enum RedisMode {
+ /**
+ * 单机
+ */
+ SINGLE,
+ /**
+ * 集群
+ */
+ CLUSTER,
+ /**
+ * 哨兵
+ */
+ SENTINEL;
+
+ }
+
}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/redisson/KeyPrefixMapper.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/redisson/KeyPrefixMapper.java
new file mode 100644
index 000000000..ffe5579b8
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/redisson/KeyPrefixMapper.java
@@ -0,0 +1,42 @@
+package com.ruoyi.framework.config.redisson;
+
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.api.NameMapper;
+
+/**
+ * redisson key 自动加前缀 解决多应用共用一个redis环境时key覆盖的问题
+ *
+ * @author im_libin@yeah.net
+ * @date 2022/3/21 2:50 下午
+ */
+public class KeyPrefixMapper implements NameMapper {
+
+ private final String keyPrefix;
+
+ public KeyPrefixMapper(String keyPrefix) {
+ this.keyPrefix = keyPrefix + ":";
+ }
+
+ @Override
+ public String map(String name) {
+ if (StringUtils.isBlank(name)) {
+ return null;
+ }
+ if (!name.startsWith(keyPrefix)) {
+ return keyPrefix + name;
+ } else {
+ return name;
+ }
+ }
+
+ @Override
+ public String unmap(String name) {
+ if (StringUtils.isBlank(name)) {
+ return null;
+ }
+ if (name.startsWith(keyPrefix)) {
+ return name.substring(keyPrefix.length());
+ }
+ return name;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/redisson/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/redisson/RedisConfig.java
new file mode 100644
index 000000000..fa2a9a32d
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/redisson/RedisConfig.java
@@ -0,0 +1,293 @@
+package com.ruoyi.framework.config.redisson;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.config.properties.RedissonProperties;
+import com.ruoyi.framework.config.properties.RedissonProperties.ClusterServersConfig;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import javax.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.Redisson;
+import org.redisson.api.DefaultNameMapper;
+import org.redisson.api.NameMapper;
+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.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+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 org.springframework.context.annotation.Primary;
+
+/**
+ * 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://";
+
+ @Resource
+ private RedisProperties redisProperties;
+
+ @Resource
+ private RedissonProperties redissonProperties;
+
+ /**
+ * 单节点模式
+ */
+ @Primary
+ @Bean(name = "redissonClient", destroyMethod = "shutdown")
+ @ConditionalOnProperty(name = "redisson.mode", havingValue = RedissonProperties.MODE_SINGLE)
+ @ConditionalOnMissingBean(RedissonClient.class)
+ RedissonClient single() {
+ RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
+ if (ObjectUtil.isNull(singleServerConfig)) {
+ throw new IllegalArgumentException("Redis connection 'redisson.singleServerConfig' is empty");
+ }
+ Config config = getConfig();
+ // 单机模式
+ config.useSingleServer()
+ .setNameMapper(getNameMapper())
+ .setAddress(getRedisProtocolPrefix() + 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())
+ .setClientName(singleServerConfig.getClientName())
+ .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
+ .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
+ .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
+ .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize());
+ log.info("初始化 redis 配置: [mode={}, address={}]", redissonProperties.getMode(), redisProperties.getHost() + ":" + redisProperties.getPort());
+ return Redisson.create(config);
+ }
+
+ /**
+ * 哨兵模式
+ */
+ @Primary
+ @Bean(name = "redissonClient", destroyMethod = "shutdown")
+ @ConditionalOnProperty(name = "redisson.mode", havingValue = RedissonProperties.MODE_SENTINEL)
+ @ConditionalOnMissingBean(RedissonClient.class)
+ RedissonClient sentinel() {
+ RedissonProperties.ClusterServersConfig clusterServersConfig = getClusterServersConfig();
+ String finalPrefix = getRedisProtocolPrefix();
+ List nodes = redisProperties.getSentinel().getNodes()
+ .stream()
+ .map(node -> finalPrefix + node)
+ .collect(Collectors.toList());
+ Config config = getConfig();
+ // 哨兵方式
+ config.useSentinelServers()
+ .setCheckSentinelsList(false)
+ .setNameMapper(getNameMapper())
+ .setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
+ .setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
+ .setMasterName(redisProperties.getSentinel().getMaster())
+ .setTimeout(clusterServersConfig.getTimeout())
+ .setRetryAttempts(clusterServersConfig.getRetryAttempts())
+ .setRetryInterval(clusterServersConfig.getRetryInterval())
+ .setClientName(clusterServersConfig.getClientName())
+ .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
+ .setPingConnectionInterval(clusterServersConfig.getPingConnectionInterval())
+ .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
+ .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
+ .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
+ .setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
+ .setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
+ .setReadMode(clusterServersConfig.getReadMode())
+ .setSubscriptionMode(clusterServersConfig.getSubscriptionMode())
+ .setSentinelAddresses(nodes);
+ log.info("初始化 redis 配置: [mode={}, master={}, nodes={}]", redissonProperties.getMode(), redisProperties.getSentinel().getMaster(),
+ nodes);
+ return Redisson.create(config);
+ }
+
+
+ /**
+ * 集群模式
+ */
+ @Primary
+ @Bean(name = "redissonClient", destroyMethod = "shutdown")
+ @ConditionalOnProperty(name = "redisson.mode", havingValue = RedissonProperties.MODE_CLUSTER)
+ @ConditionalOnMissingBean(RedissonClient.class)
+ RedissonClient cluster() {
+ RedissonProperties.ClusterServersConfig clusterServersConfig = getClusterServersConfig();
+ String finalPrefix = getRedisProtocolPrefix();
+ List nodes = redisProperties.getCluster().getNodes()
+ .stream()
+ .map(node -> finalPrefix + node)
+ .collect(Collectors.toList());
+ Config config = getConfig();
+ // 集群方式
+ config.useClusterServers()
+ .setNameMapper(getNameMapper())
+ .setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
+ .setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
+ .setTimeout(clusterServersConfig.getTimeout())
+ .setRetryAttempts(clusterServersConfig.getRetryAttempts())
+ .setRetryInterval(clusterServersConfig.getRetryInterval())
+ .setClientName(clusterServersConfig.getClientName())
+ .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
+ .setPingConnectionInterval(clusterServersConfig.getPingConnectionInterval())
+ .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
+ .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
+ .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
+ .setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
+ .setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
+ .setReadMode(clusterServersConfig.getReadMode())
+ .setSubscriptionMode(clusterServersConfig.getSubscriptionMode())
+ .setNodeAddresses(nodes);
+ log.info("初始化 redis 配置: [mode={}, nodes={}]", redissonProperties.getMode(), nodes);
+ return Redisson.create(config);
+ }
+
+ private String getRedisProtocolPrefix(){
+ return redisProperties.isSsl() ? REDISS_PROTOCOL_PREFIX : REDIS_PROTOCOL_PREFIX;
+ }
+
+ private Config getConfig(){
+ Config config = new Config();
+ config.setThreads(redissonProperties.getThreads())
+ .setNettyThreads(redissonProperties.getNettyThreads())
+ .setCodec(JsonJacksonCodec.INSTANCE)
+ .setTransportMode(redissonProperties.getTransportMode());
+ return config;
+ }
+
+ private ClusterServersConfig getClusterServersConfig() {
+ RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();
+ if (ObjectUtil.isNull(clusterServersConfig)){
+ throw new IllegalArgumentException("Redis connection 'redisson.clusterServersConfig' is empty");
+ }
+ return clusterServersConfig;
+ }
+
+ private NameMapper getNameMapper() {
+ if (StringUtils.isBlank(redissonProperties.getKeyPrefix())){
+ return new DefaultNameMapper();
+ }
+ return new KeyPrefixMapper(redissonProperties.getKeyPrefix());
+ }
+
+
+ /**
+ * 整合spring-cache
+ */
+ @Bean
+ public CacheManager cacheManager(RedissonClient redissonClient) {
+ List cacheGroup = redissonProperties.getCacheGroup();
+ Map config = new HashMap<>(cacheGroup.size());
+ 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:
+ * sentinel:
+ * master: redis_master
+ * nodes:
+ * - 192.168.0.100:26379
+ * - 192.168.0.101:26379
+ * - 192.168.0.102:26379
+ * cluster:
+ * nodes:
+ * - 192.168.0.100:6379
+ * - 192.168.0.101:6379
+ * - 192.168.0.102:6379
+ * # 地址
+ * host: localhost
+ * # 端口,默认为6379
+ * port: 6379
+ * # 密码
+ * password: 12345678
+ * # 连接超时时间
+ * timeout: 10s
+ * # 是否开启ssl
+ * ssl: false
+ *
+ * redisson:
+ * # 线程池数量
+ * threads: 16
+ * # Netty线程池数量
+ * nettyThreads: 32
+ * # 传输模式
+ * transportMode: "NIO"
+ * # 缓存key前缀
+ * keyPrefix: ${ruoyi.name}
+ * # 配置方式
+ * mode: "SINGLE"
+ * --- # 当mode: "SINGLE" 配置 singleServerConfig节点,当mode: "CLUSTER/SENTINEL"时 配置clusterServersConfig节点
+ * # 单节点配置
+ * singleServerConfig:
+ * # 客户端名称
+ * clientName: ${ruoyi.name}
+ * # 最小空闲连接数
+ * connectionMinimumIdleSize: 8
+ * # 连接池大小
+ * connectionPoolSize: 32
+ * # 连接空闲超时,单位:毫秒
+ * idleConnectionTimeout: 10000
+ * # 命令等待超时,单位:毫秒
+ * timeout: 3000
+ * # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
+ * retryAttempts: 3
+ * # 命令重试发送时间间隔,单位:毫秒
+ * retryInterval: 1500
+ * # 发布和订阅连接池大小
+ * subscriptionConnectionPoolSize: 50
+ * # 集群配置
+ * 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
+ * # 发布和订阅连接池大小
+ * subscriptionConnectionPoolSize: 50
+ * # 读取模式
+ * readMode: "SLAVE"
+ * # 订阅模式
+ * subscriptionMode: "MASTER"
+ */
+}