ソースを参照

统一裸Jedis与Redisson的Redis连接配置并支持密码

新增 JedisFactory 复用 spring.data.redis 的 host/port/可选密码,替换
各处硬编码 new Jedis("localhost", 6379)(语言缓存、地址/路径计算、
RedisUtils),均改为 try-with-resources 关闭;保留原裸 Jedis 的 DB 0
不改变现有键所在库。

Redisson 地址与密码改从 spring.redisson.address、
spring.data.redis.password 注入,未配置密码时免密连接,与 Lettuce
共口径;ruoyi-framework 补 spring-boot-starter-test 依赖及
RedissonConfig/JedisFactory 单测。
qmj 1 日 前
親
コミット
c5d940d7c2

+ 8 - 2
ruoyi-admin/src/main/java/com/ruoyi/app/promotion/SalesPromotionController.java

@@ -17,6 +17,7 @@ import com.ruoyi.system.domain.PosOrder;
 import com.ruoyi.system.mapper.PosOrderMapper;
 import com.ruoyi.system.utils.Auth;
 import com.ruoyi.system.utils.JwtUtil;
+import com.ruoyi.system.utils.JedisFactory;
 import io.swagger.models.auth.In;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -47,6 +48,9 @@ public class SalesPromotionController extends BaseController {
     @Autowired
     private PosOrderMapper posOrderMapper;
 
+    @Autowired
+    private JedisFactory jedisFactory;
+
     /**
      * 获取可参于促销活动
      *
@@ -133,8 +137,10 @@ public class SalesPromotionController extends BaseController {
 
     private String getLanguage(String uid) {
 
-        Jedis jedis = new Jedis("localhost", 6379);
-        String lang = jedis.get(uid);
+        String lang;
+        try (Jedis jedis = jedisFactory.create()) {
+            lang = jedis.get(uid);
+        }
         System.out.println("从redis获取的语言是:" + lang);
         String result = "0";
         if ("zh-CN".equals(lang)) {

+ 8 - 2
ruoyi-admin/src/main/java/com/ruoyi/app/user/VipUserQuanyiController.java

@@ -25,6 +25,7 @@ import com.ruoyi.system.service.ISalesPromotionService;
 import com.ruoyi.system.service.IVipQuanyiService;
 import com.ruoyi.system.utils.Auth;
 import com.ruoyi.system.utils.JwtUtil;
+import com.ruoyi.system.utils.JedisFactory;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.apache.commons.lang3.time.DateUtils;
@@ -57,6 +58,9 @@ public class VipUserQuanyiController extends BaseController {
     @Autowired
     private ISalesPromotionService promotionService;
 
+    @Autowired
+    private JedisFactory jedisFactory;
+
     @Anonymous
     @Auth
     @ApiOperation("可用活动分页列表")
@@ -95,8 +99,10 @@ public class VipUserQuanyiController extends BaseController {
 
     private String getLanguage(String uid) {
 
-        Jedis jedis = new Jedis("localhost", 6379);
-        String lang = jedis.get(uid);
+        String lang;
+        try (Jedis jedis = jedisFactory.create()) {
+            lang = jedis.get(uid);
+        }
         System.out.println("从redis获取的语言是:" + lang);
         String result = "0";
         if ("zh-CN".equals(lang)) {

+ 15 - 8
ruoyi-admin/src/main/java/com/ruoyi/app/utils/SysFileInfoController.java

@@ -17,6 +17,7 @@ import com.ruoyi.system.mapper.PosFreightMapper;
 import com.ruoyi.system.service.IPosFreightService;
 import com.ruoyi.system.utils.AddPush;
 import com.ruoyi.system.utils.GetArea;
+import com.ruoyi.system.utils.JedisFactory;
 import com.ruoyi.web.controller.common.CommonController;
 import io.swagger.models.auth.In;
 import org.slf4j.Logger;
@@ -39,6 +40,8 @@ public class SysFileInfoController extends BaseController {
     private IPosFreightService posFreightService;
     @Autowired
     private PosFreightMapper posFreightMapper;
+    @Autowired
+    private JedisFactory jedisFactory;
     private static final Logger log = LoggerFactory.getLogger(SysFileInfoController.class);
 
     //上传
@@ -59,9 +62,12 @@ public class SysFileInfoController extends BaseController {
     public AjaxResult getLocationAddr(@RequestParam String latlng,
                                       @RequestParam Integer type,
                                       @RequestParam(defaultValue = "") String id) {
-        Jedis jedis = new Jedis("localhost", 6379);
         GetArea area = new GetArea();
-        String lang = jedis.get(id) == null ? "zh-TW" : jedis.get(id);
+        String lang;
+        try (Jedis jedis = jedisFactory.create()) {
+            String savedLanguage = jedis.get(id);
+            lang = savedLanguage == null ? "zh-TW" : savedLanguage;
+        }
         JSONObject reg;
         //type=0 百度逆地理分支已停用(2026-09-29 标记),保留兜底不删;当前在用的是 type=1 谷歌分支
         if (type == 0) {
@@ -77,8 +83,11 @@ public class SysFileInfoController extends BaseController {
     @GetMapping("/getAddr")
     public AjaxResult getAddr(@RequestParam String latlng,
                               @RequestParam(defaultValue = "") String id) {
-        Jedis jedis = new Jedis("localhost", 6379);
-        String lang = jedis.get(id) == null ? "zh-TW" : jedis.get(id);
+        String lang;
+        try (Jedis jedis = jedisFactory.create()) {
+            String savedLanguage = jedis.get(id);
+            lang = savedLanguage == null ? "zh-TW" : savedLanguage;
+        }
         GetArea area = new GetArea();
         JSONObject reg = area.getgoogleadd(latlng, lang);
         return success(reg);
@@ -197,8 +206,7 @@ public class SysFileInfoController extends BaseController {
                                     @RequestParam String latlng2,
                                     @RequestParam(defaultValue = "") String id) {
         log.info("谷歌地图:开始处理路径计算请求 -> ID: {}, 坐标1: {}, 坐标2: {}", id, latlng1, latlng2);
-        try(Jedis jedis=new Jedis("localhost", 6379);) {
-            //Jedis jedis = new Jedis("localhost", 6379);
+        try(Jedis jedis=jedisFactory.create()) {
             String lang = jedis.get(id) == null ? "zh-TW" : jedis.get(id);
             GetArea area = new GetArea();
             JSONObject reg = area.getluxian(latlng1, latlng2, lang);
@@ -226,8 +234,7 @@ public class SysFileInfoController extends BaseController {
                                     @RequestParam String lnglat2,
                                     @RequestParam(defaultValue = "") String id) {
         log.info("Mapbox地图:开始处理路径计算请求 -> ID: {}, 坐标1: {}, 坐标2: {}", id, lnglat1, lnglat2);
-        try(Jedis jedis=new Jedis("localhost", 6379);) {
-            //Jedis jedis = new Jedis("localhost", 6379);
+        try(Jedis jedis=jedisFactory.create()) {
             String lang = jedis.get(id) == null ? "zh-TW" : jedis.get(id);
             GetArea area = new GetArea();
             JSONObject reg = area.getmpluxian(lnglat1, lnglat2);

+ 7 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java

@@ -18,6 +18,7 @@ import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.framework.web.service.SysLoginService;
 import com.ruoyi.framework.web.service.SysPermissionService;
 import com.ruoyi.system.service.ISysMenuService;
+import com.ruoyi.system.utils.JedisFactory;
 import redis.clients.jedis.Jedis;
 
 /**
@@ -37,6 +38,9 @@ public class SysLoginController
     @Autowired
     private SysPermissionService permissionService;
 
+    @Autowired
+    private JedisFactory jedisFactory;
+
     /**
      * 登录方法
      *
@@ -57,8 +61,9 @@ public class SysLoginController
     @GetMapping("/changeLanguages")
     public AjaxResult changeLanguage(String lang,String id)
     {
-        Jedis jedis = new Jedis("localhost", 6379);
-        jedis.set(id, lang);
+        try (Jedis jedis = jedisFactory.create()) {
+            jedis.set(id, lang);
+        }
         System.out.println(id+"切换的语言是:" + lang);
         return AjaxResult.success();
     }

+ 2 - 2
ruoyi-admin/src/main/resources/application.yml

@@ -191,7 +191,7 @@ spring:
       port: 6379
       # 数据库索引
       database: 1
-      # 密码
+      # 可选:仅需在启用密码的环境设置 REDIS_PASSWORD;Lettuce、Redisson 和裸 Jedis 共用
       password:
       # 连接超时时间
       timeout: 10s
@@ -207,7 +207,7 @@ spring:
           max-wait: -1ms
   redisson:
     address: redis://127.0.0.1:6379
-    # password: 不要写这一行
+    # 密码沿用 spring.data.redis.password,未配置时免密连接
 
 # token配置
 token:

+ 5 - 0
ruoyi-framework/pom.xml

@@ -72,6 +72,11 @@
             <artifactId>firebase-admin</artifactId>
             <version>9.1.1</version>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
 </project>

+ 21 - 4
ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedissonConfig.java

@@ -3,18 +3,35 @@ package com.ruoyi.framework.config;
 import org.redisson.Redisson;
 import org.redisson.api.RedissonClient;
 import org.redisson.config.Config;
+import org.redisson.config.SingleServerConfig;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
 @Configuration
 public class RedissonConfig {
 
+    private final String address;
+    private final String password;
+
+    public RedissonConfig(@Value("${spring.redisson.address:redis://127.0.0.1:6379}") String address,
+                          @Value("${spring.data.redis.password:}") String password) {
+        this.address = address;
+        this.password = password;
+    }
+
     @Bean
     public RedissonClient redissonClient() {
+        return Redisson.create(createConfig());
+    }
+
+    Config createConfig() {
         Config config = new Config();
-        config.useSingleServer()
-                .setAddress("redis://127.0.0.1:6379");
-        // 如果有密码,添加 .setPassword("你的密码");
-        return Redisson.create(config);
+        SingleServerConfig singleServer = config.useSingleServer().setAddress(address);
+        // 与 Lettuce 共用密码配置;未配置时不发送 AUTH,兼容免密 Redis。
+        if (password != null && !password.isBlank()) {
+            singleServer.setPassword(password);
+        }
+        return config;
     }
 }

+ 23 - 0
ruoyi-framework/src/test/java/com/ruoyi/framework/config/RedissonConfigTest.java

@@ -0,0 +1,23 @@
+package com.ruoyi.framework.config;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+class RedissonConfigTest {
+
+    @Test
+    void configuredPasswordIsUsedForRedisson() {
+        RedissonConfig config = new RedissonConfig("redis://127.0.0.1:6379", "secret");
+
+        assertEquals("secret", config.createConfig().useSingleServer().getPassword());
+    }
+
+    @Test
+    void missingPasswordLeavesRedissonUnauthenticated() {
+        RedissonConfig config = new RedissonConfig("redis://127.0.0.1:6379", "");
+
+        assertNull(config.createConfig().useSingleServer().getPassword());
+    }
+}

+ 35 - 0
ruoyi-system/src/main/java/com/ruoyi/system/utils/JedisFactory.java

@@ -0,0 +1,35 @@
+package com.ruoyi.system.utils;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import redis.clients.jedis.Jedis;
+
+@Component
+public class JedisFactory {
+
+    private final String host;
+    private final int port;
+    private final String password;
+
+    public JedisFactory(@Value("${spring.data.redis.host:localhost}") String host,
+                        @Value("${spring.data.redis.port:6379}") int port,
+                        @Value("${spring.data.redis.password:}") String password) {
+        this.host = host;
+        this.port = port;
+        this.password = password;
+    }
+
+    public Jedis create() {
+        // 保留原裸 Jedis 的 DB 0;仅复用连接地址与可选密码,不改变现有缓存键所在库。
+        Jedis jedis = new Jedis(host, port);
+        try {
+            if (password != null && !password.isBlank()) {
+                jedis.auth(password);
+            }
+            return jedis;
+        } catch (RuntimeException e) {
+            jedis.close();
+            throw e;
+        }
+    }
+}

+ 6 - 10
ruoyi-system/src/main/java/com/ruoyi/system/utils/RedisUtils.java

@@ -2,12 +2,13 @@ package com.ruoyi.system.utils;
 
 import org.springframework.stereotype.Component;
 import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
+import org.springframework.beans.factory.annotation.Autowired;
 
 @Component
 public class RedisUtils {
 
-    Jedis jedis = new Jedis("localhost", 6379);
+    @Autowired
+    private JedisFactory jedisFactory;
 
     /**
      * 读取缓存
@@ -16,11 +17,8 @@ public class RedisUtils {
      * @return
      */
     public String get( String key) {
-        try{
-            String value = jedis.get(key);
-            return value;
-        }finally{
-            jedis.close();
+        try (Jedis jedis = jedisFactory.create()) {
+            return jedis.get(key);
         }
 
     }
@@ -29,11 +27,9 @@ public class RedisUtils {
      * 写入缓存
      */
     public boolean set(final String key, String value) {
-        try {
+        try (Jedis jedis = jedisFactory.create()) {
             jedis.set(key, value);
             return true;
-        } finally {
-            jedis.close();
         }
     }
 

+ 38 - 0
ruoyi-system/src/test/java/com/ruoyi/system/utils/JedisFactoryTest.java

@@ -0,0 +1,38 @@
+package com.ruoyi.system.utils;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedConstruction;
+import redis.clients.jedis.Jedis;
+
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+class JedisFactoryTest {
+
+    @Test
+    void configuredPasswordAuthenticatesBeforeReturningConnection() {
+        try (MockedConstruction<Jedis> construction = mockConstruction(Jedis.class)) {
+            Jedis jedis = new JedisFactory("localhost", 6379, "secret").create();
+
+            assertSame(construction.constructed().get(0), jedis);
+            assertEquals(1, construction.constructed().size());
+            verify(jedis).auth("secret");
+        }
+    }
+
+    @Test
+    void missingOrBlankPasswordDoesNotAuthenticate() {
+        try (MockedConstruction<Jedis> construction = mockConstruction(Jedis.class)) {
+            new JedisFactory("localhost", 6379, null).create();
+            new JedisFactory("localhost", 6379, " ").create();
+
+            assertEquals(2, construction.constructed().size());
+            for (Jedis jedis : construction.constructed()) {
+                verify(jedis, never()).auth(org.mockito.ArgumentMatchers.anyString());
+            }
+        }
+    }
+}