Quellcode durchsuchen

新增Redis批量设置带过期时间的字典工具方法

woody vor 1 Jahr
Ursprung
Commit
34de2703ad

+ 36 - 0
framework-redis/src/main/java/com/chelvc/framework/redis/util/RedisUtils.java

@@ -164,6 +164,14 @@ public class RedisUtils implements ApplicationContextAware {
                     "if redis.call('MSETNX', unpack(args)) == 1 then for i = 1, #KEYS do " +
                     "redis.call('EXPIRE', KEYS[i], ARGV[#ARGV]) end return 1 else return 0 end";
 
+    /**
+     * Redis批量设置字典脚本(如果成功则更新过期时间)
+     */
+    private static final String HMSET_WITH_DURATION_SCRIPT =
+            "local args = {} table.insert(args, KEYS[1]) for i = 2, #KEYS do table.insert(args, KEYS[i]) " +
+                    "table.insert(args, ARGV[i]) end local result = redis.call('HMSET', unpack(args)) " +
+                    "if result[1] == false then return 0 else return redis.call('EXPIRE', KEYS[1], ARGV[1]) end";
+
     /**
      * Redis连接工厂
      */
@@ -670,6 +678,34 @@ public class RedisUtils implements ApplicationContextAware {
         return Boolean.TRUE.equals(template.execute(script, keys, values));
     }
 
+    /**
+     * 批量设置带过期时间的字典值
+     *
+     * @param template Redis操作模版实例
+     * @param key      字典标识
+     * @param mapping  键/值映射表
+     * @param duration 有效时间
+     * @param <K>      键类型
+     * @return true/false
+     */
+    public static <K> boolean hmset(@NonNull RedisTemplate<K, ?> template, @NonNull K key,
+                                    @NonNull Map<K, ?> mapping, @NonNull Duration duration) {
+        if (CollectionUtils.isEmpty(mapping)) {
+            return false;
+        }
+        int i = 0;
+        List<K> keys = Lists.newArrayListWithCapacity(mapping.size() + 1);
+        keys.add(key);
+        Object[] values = new Object[mapping.size() + 1];
+        values[i++] = duration.getSeconds();
+        for (Map.Entry<K, ?> entry : mapping.entrySet()) {
+            keys.add(entry.getKey());
+            values[i++] = entry.getValue();
+        }
+        RedisScript<Boolean> script = new DefaultRedisScript<>(HMSET_WITH_DURATION_SCRIPT, Boolean.class);
+        return Boolean.TRUE.equals(template.execute(script, keys, values));
+    }
+
     /**
      * 数字自增1,如果键不存在则对值初始化
      *

+ 4 - 2
framework-security/src/main/java/com/chelvc/framework/security/context/SecurityContextHolder.java

@@ -1,6 +1,7 @@
 package com.chelvc.framework.security.context;
 
 import java.io.Serializable;
+import java.time.Duration;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
@@ -20,6 +21,7 @@ import com.chelvc.framework.base.model.Session;
 import com.chelvc.framework.base.model.Terminal;
 import com.chelvc.framework.base.util.ObjectUtils;
 import com.chelvc.framework.base.util.StringUtils;
+import com.chelvc.framework.redis.util.RedisUtils;
 import com.chelvc.framework.security.config.SecurityProperties;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.google.common.collect.Maps;
@@ -370,8 +372,8 @@ public class SecurityContextHolder implements ApplicationContextAware, ServletRe
         if (StringUtils.nonEmpty(business)) {
             context.put("business", business);
         }
-        redisTemplate.opsForHash().putAll(key, context);
-        redisTemplate.expireAt(key, token.getExpiration());
+        long millis = Math.max(token.getExpiration().getTime() - System.currentTimeMillis(), 0);
+        RedisUtils.hmset(redisTemplate, key, context, Duration.ofMillis(millis));
     }
 
     /**