From 3d1790ad64d9b03f1cc6fe3fd0ac5e9ff35ecf86 Mon Sep 17 00:00:00 2001 From: wh Date: Thu, 9 Apr 2026 13:27:47 +0800 Subject: [PATCH] =?UTF-8?q?feat(common):=20=E6=B7=BB=E5=8A=A0=20RedisKeyMa?= =?UTF-8?q?nager/RedisService/RedisConfig=20(T009)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/label/common/config/RedisConfig.java | 24 ++++++++ .../label/common/redis/RedisKeyManager.java | 25 ++++++++ .../com/label/common/redis/RedisService.java | 61 +++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 src/main/java/com/label/common/config/RedisConfig.java create mode 100644 src/main/java/com/label/common/redis/RedisKeyManager.java create mode 100644 src/main/java/com/label/common/redis/RedisService.java diff --git a/src/main/java/com/label/common/config/RedisConfig.java b/src/main/java/com/label/common/config/RedisConfig.java new file mode 100644 index 0000000..d2394b9 --- /dev/null +++ b/src/main/java/com/label/common/config/RedisConfig.java @@ -0,0 +1,24 @@ +package com.label.common.config; + +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; + +@Configuration +public class RedisConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + StringRedisSerializer serializer = new StringRedisSerializer(); + template.setKeySerializer(serializer); + template.setValueSerializer(serializer); + template.setHashKeySerializer(serializer); + template.setHashValueSerializer(serializer); + template.afterPropertiesSet(); + return template; + } +} diff --git a/src/main/java/com/label/common/redis/RedisKeyManager.java b/src/main/java/com/label/common/redis/RedisKeyManager.java new file mode 100644 index 0000000..d0286b1 --- /dev/null +++ b/src/main/java/com/label/common/redis/RedisKeyManager.java @@ -0,0 +1,25 @@ +package com.label.common.redis; + +/** + * Centralized Redis key naming conventions. + * All keys follow the pattern: prefix:{id} + */ +public final class RedisKeyManager { + + private RedisKeyManager() {} + + /** Session token key: token:{uuid} */ + public static String tokenKey(String uuid) { + return "token:" + uuid; + } + + /** User permission cache key: user:perm:{userId} */ + public static String userPermKey(Long userId) { + return "user:perm:" + userId; + } + + /** Task claim distributed lock key: task:claim:{taskId} */ + public static String taskClaimKey(Long taskId) { + return "task:claim:" + taskId; + } +} diff --git a/src/main/java/com/label/common/redis/RedisService.java b/src/main/java/com/label/common/redis/RedisService.java new file mode 100644 index 0000000..af305ae --- /dev/null +++ b/src/main/java/com/label/common/redis/RedisService.java @@ -0,0 +1,61 @@ +package com.label.common.redis; + +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +@Service +@RequiredArgsConstructor +public class RedisService { + + private final RedisTemplate redisTemplate; + + // String operations + + public void set(String key, String value, long ttlSeconds) { + redisTemplate.opsForValue().set(key, value, ttlSeconds, TimeUnit.SECONDS); + } + + public String get(String key) { + return redisTemplate.opsForValue().get(key); + } + + public void delete(String key) { + redisTemplate.delete(key); + } + + public boolean exists(String key) { + return Boolean.TRUE.equals(redisTemplate.hasKey(key)); + } + + /** Set if absent (NX). Returns true if key was set (lock acquired). */ + public boolean setIfAbsent(String key, String value, long ttlSeconds) { + Boolean result = redisTemplate.opsForValue() + .setIfAbsent(key, value, ttlSeconds, TimeUnit.SECONDS); + return Boolean.TRUE.equals(result); + } + + /** Refresh TTL on an existing key (sliding expiration). */ + public void expire(String key, long ttlSeconds) { + redisTemplate.expire(key, ttlSeconds, TimeUnit.SECONDS); + } + + // Hash operations (for token storage: token:{uuid} → Hash) + + public void hSetAll(String key, Map entries, long ttlSeconds) { + redisTemplate.opsForHash().putAll(key, entries); + redisTemplate.expire(key, ttlSeconds, TimeUnit.SECONDS); + } + + public Map hGetAll(String key) { + return redisTemplate.opsForHash().entries(key); + } + + public String hGet(String key, String field) { + Object val = redisTemplate.opsForHash().get(key, field); + return val != null ? val.toString() : null; + } +}