[Redis 客户端整合] SpringBoot 整合 Lettuce
一、简介
在使用SpringBoot搭建微服务的时候, 很多时候需要用Redis来缓存一些数据 , 存储一些高频率访问的数据。SpringBoot整合Redis所常用的Redis常用客户端有三个:
- Jedis api
- redisson
- lettuce
本文采用lettuce来访问Redis, 在Spring boot2之后, 对redis连接的支持, 默认就采用了lettuce
二、导入依赖
<!-- SpringData 用于简化数据库访问-->
<!--默认是lettuce客户端-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis依赖commons-pool 这个依赖一定要添加 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
三、配置连接信息
在application.yml
文件中, 配置 Redis 连接信息
spring:
redis:
host: 127.0.0.1
port: 6379
password: 123456
lettuce:
pool:
max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
max-idle: 8 # 连接池中的最大空闲连接
min-idle: 0 # 连接池中的最小空闲连接
max-wait: 1000 # 连接池最大阻塞等待时间(使用负值表示没有限制)
shutdown-timeout: 100 # 关闭超时时间
四、RedisConfig类介绍
缓存配置类RedisConfig用于调优缓存默认配置, 使RedisTemplate<String,Object>
的类型兼容性更高
在redisTemplate()
这个方法中, 用Jackson2JsonRedisSerializer
更换掉了Redis默认的序列化方式 JdkSerializationRedisSerializer
spring-data-redis中序列化类有一下几个:
GenericToStringSerializer
: 可以将任何对象泛化为字符串并序列化Jackson2JsonRedisSerializer
: 序列化 Object 对象为 Json 字符串 (与JacksonJsonRedisSerializer
相同)JdkSerializationRedisSerializer
: 序列化 Java 对象StringRedisSerializer
: 简单的字符串序列化
JdkSerializationRedisSerializer
序列化 : 被序列化对象必须实现Serializable
接口 , 被序列化除属性内容还有其他内容 , 长度长且不易阅读 , 默认就是采用这种序列化方式
存储内容如下:
JdkSerializationRedisSerializer
序列化 : 被序列化对象不需要实现Serializable
接口 , 被序列化的结果清晰 , 内容易阅读 , 且存储字节少 , 速度快
存储内容如下:
StringRedisSerializer
序列化 : 一般如果key、value都是字符串的话 , 用这个就可以了
五、编写RedisConfig类
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
/**
* 自定义缓存key的生成策略,默认的生成策略是看不懂的(乱码内容)
* 通过Spring的依赖注入特性进行自定义的配置注入并且此类是一个配置类, 可以更多程度的自定义配置
* @return
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(target.getClass().getName());
stringBuilder.append(method.getName());
for (Object obj :
params) {
stringBuilder.append(obj.toString());
}
return stringBuilder.toString();
}
};
}
/**
* 缓存配置管理器
* @param factory
* @return
*/
@Bean
public CacheManager cacheManager(LettuceConnectionFactory factory){
//以锁写入的方式创建RedisCacheWriter对象
RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(factory);
//创建默认缓存配置对象
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheManager cacheManager = new RedisCacheManager(writer,config);
return cacheManager;
}
//@ConditionalOnMissingBean(name="redisTemplate") 如果没有RedisTemplate的Bean则使用该注解定义的Bean
@Bean
public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory factory){
RedisTemplate<String,Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//在使用注解@Bean返回RedisTemplate的时候,同时配置hashKey与hashValue的序列化方式
//key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
//value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
//hash的key采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
//hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
五、使用RedisTemplate
(1)注入 RedisTemplate 对象
在要使用 Redis模板 的类中注入 RedisTemplate 对象
@Autowired
private RedisTemplate<String,Object> redisTemplate;
(2)使用 RedisTemplate 对象
redisTemplate 类是对lettuce的进一步封装 , 因此他的方法并不与Redis语法一一对应。
对于Redis中所有类型共有的命令, 可以使用redisTemplate.方法()
对Redis进行操作
对于Redis中特定类型的命令, 需要使用redisTemplate.opsFor类型().方法()
对Redis进行操作
- String 类型 :
redisTemplate.opsForValue().方法()
- Hash 类型 :
redisTemplate.opsForHash().方法()
- List 类型 :
redisTemplate.opsForList().方法()
- Set 类型 :
redisTemplate.opsForSet().方法()
- ZSet 类型 :
redisTemplate.opsForZSet().方法()
(3) 使用 RedisTemplate 注入 ValueOperations
如果每次调用方法, 都用redisTemplate.opsFor类型().方法()
, 在代码中会有很多重复的redisTemplate.opsFor类型()
为了解决这个问题 , 我们可以使用 RedisTemplate 注入 类型 + Operations
以String类型为例:
@Autowired
private RedisTemplate<String,Object> redisTemplate;
@Resource(name = "redisTemplate")
private ValueOperations<String, Object> vOps; // 相当于 vOps = redisTemplate.opsForValue()
RedisTemplate 类型和 ValueOperations 类型并没有任何的关系, 他之所以可以注入是因为Spring在注入时对其进行了类型转换。若想要深入了解redisTemplate如何注入到ValueOperations, 可以查看此博客: redisTemplate如何注入到ValueOperations
(4) 实例 - RedisTemplate 操作 String 类型
@Resource(name = "redisTemplate")
private ValueOperations<String, Object> vOps;
public String gerString(String key){
String val = null;
if(redisTemplate.hasKey(key)){
val = (String) vOps.get(key);
log.info("从Redis查询");
}else {
val ="模拟MySql查询";
log.info("从MySql查询");
vOps.set(key,val);
}
return val;
}
(5) 实例 - RedisTemplate 操作 Hash 类型
User实体类
@Data
public class User implements Serializable {
private String id;
private String name;
private Integer age;
}
查询 User 方法
@Resource(name = "redisTemplate")
private HashOperations<String,String,User> hOps;
public User selectUserById(String id){
if(hOps.hasKey("user", id)){
log.info("查询Redis");
return (User) hOps.get("user",id);
}else{
User user = new User();
user.setId(id);
user.setName("王五");
user.setAge(20);
log.info("查询Mysql数据库");
hOps.put("user",id,user);
return user;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!