前言
- 经常使用redis,固定前缀key每次都定义在当前类下,查询或储存redis时总是需要key+参数去操作,开发人员固守自封,后期维护成本加大,也看的不是很直观。
- 在最近的项目业务中,发现了比较好的处理方式,所以拿出来一起分享,当然还有很多更加优秀的方案,这里只是分享出来,供大家参考研究。
- 说一下该方案大体的思路,通过定义公共key键值类,定义公共的查询key键值方法,来来统一管理,大大提升了代码的通用性。
- 当然,该方案思路不仅限于redis,可合理化的修改为自己想要的方案,这里通过redis实例来进行展示。
一、pom.xml文件
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.6.2</version>
</dependency>
二、key值公共管理类定义
/**
* 定义公共Key
*/
public interface RedisKey {
/**
* 公共头部
*/
String KEY_REDIS = "wss:";
//样例数据,可自行定义规则
interface childKey {
/**
* 用户详情请求 - 1
* 0 -> User.class
*/
String USER_KEY = "user:get:{0}";
/**
* 机构详情请求
* 0 -> 机构ID
* 1 -> Org.class
*/
String ORG_KEY = "org:sev:{0}:{1}";
/**
* 用户详情请求 - 2
* 0 -> 用户ID
* 1 -> 用户名称
* 2 -> 用户年龄
*/
String USER_DETAIL_KEY = "user:get:{0}:{1}:{2}";
}
}
三、拼接key值类定义
import lombok.experimental.UtilityClass;
import org.springframework.lang.NonNull;
import java.text.MessageFormat;
/**
* 拼接key值
* @UtilityClass 相当于每个方法都加了static
*/
@UtilityClass
public final class RedisKeyName {
private String key(@NonNull String key, Object... objs) {
return MessageFormat.format(RedisKey.KEY_REDIS + key, objs);
}
/**
* 通过用户Id获取用户信息
*/
public String getUserKey(String userId) {
return key(RedisKey.childKey.USER_KEY, userId);
}
}
四、获取缓存类定义
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Objects;
@Slf4j
@Component
@RequiredArgsConstructor
public class CacheService {
private final RedisTemplate<String, Object> redisTemplate;
/**
* 获取缓存数据
**/
public <T> T getCacheByKey(String cacheKey, Class<T> clazz) {
Boolean b = redisTemplate.hasKey(cacheKey);
if (Objects.isNull(b) || Boolean.FALSE.equals(b)) {
return null;
}
try {
Object cacheObj = redisTemplate.opsForValue().get(cacheKey);
if (Objects.nonNull(cacheObj)) {
return clazz.cast(cacheObj);
}
} catch (Exception ignored) {
//如果反序列化抛错,直接重取数据
}
return null;
}
}
五、Controller定义 - 测试方法展示
import com.bi.my.util.CacheService;
import com.bi.my.util.RedisKeyName;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
/**
* 用户管理
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private CacheService cacheService;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 通过用户id获取用户信息
*/
@GetMapping("getUser")
public void getUser(String userId) {
//通过用户ID拼接对应Key(最终返回userKey为 wss:user:get:userId)
String userKey = RedisKeyName.getUserKey(userId);
//存储到redis中
redisTemplate.opsForValue().set(userKey, user, 300, TimeUnit.SECONDS);
//拿到key去redis查询
User user = cacheService.getCacheByKey(userKey, User.class);
}
}
网友评论