spring-boot-data redis
Spring Boot 提供了 Redis 集成启动器(Starter),依赖于 spring-data-redis 和 lettuce 库。 spring-data-redis:对 Reids 底层开发包高度封装,让开发者对 Redis 的 CRUD 操作起来更加方便。
创建工程
- 导入相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
引入
spring-boot-starter-data-redis
依赖就可以快速帮助我们操作Redis
配置资源 resource/application.yml
- 配置
Redis
连接源和Lecture
相关信息
spring:
datasource:
url: jdbc:mysql://主机地址:3306/stu?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
redis:
host: 主机地址
port: 端口号
password: 密码
lettuce:
pool:
max-active: 20 # 连接池最大连接数
max-wait: 1 # 最大阻塞等待时间
max-idle: 5 # 最大
min-idle: 0 # 连接池的最小空闲连接
shutdown-timeout: 100
配置 jackson
类
- 配置查询转换异常 和SON转化为对象,会转化成Map类型相关问题
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// 自定义类型转换器
SimpleModule simpleModule = new SimpleModule();
final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
// 时间转换 module - 用户 LocalDateTime 日期类型的序列化和反序列化
JavaTimeModule javaTimeModule = new JavaTimeModule();
// 配置 LocalDateTime 的序列化规则和格式化规则
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
// javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
// javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
// 添加自定义序列化器
simpleModule.addSerializer(Money.class , new MoneySerializer());
simpleModule.addDeserializer(Money.class , new MoneyDeserializer());
objectMapper.registerModule(simpleModule);
objectMapper.registerModule(javaTimeModule);
// 配置查询缓存转换异常
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 必须设置,否则无法将JSON转化为对象,会转化成Map类型
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
return objectMapper;
}
- 配置序列化
Module
可以适配非基本类型的序列化如LocalDateTime
和org.joa.Money
等
1、实现
class
的相关序列化和反序列化器
2、在相关 Module 进行序列化器的注册,如果没有相关的Module
可以采用SimpleModule
进行相关的序列化器和反序列化器的添加
3、序列化通过实现 StdSerializer
或者 JsonSerializer
进行自定义序列化的实现
// 标记成 JSON 的 Component
@JsonComponent
public class MoneySerializer extends StdSerializer<Money> {
public MoneySerializer() {
super(Money.class);
}
@Override
public void serialize(Money money, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeNumber(money.getAmountMinor());
}
}
4、反序列化通过实现 MoneyDeserializer
或者 JsonDeserializer
进行自定义反序列化的实现
@JsonComponent
public class MoneyDeserializer extends StdDeserializer<Money> {
public MoneyDeserializer() {
super(Money.class);
}
@Override
public Money deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return Money.ofMinor(CurrencyUnit.of("CNY"), p.getLongValue());
}
}
5、序列化会对 Money
的内容进行相关的改变
实现自定义序列化器
- 通过实现
RedisSerializer
进行自定义Redis
序列化器的实现,同时实现InitializingBean
接口适配Spring
public class RedisKeySerializer implements InitializingBean, RedisSerializer<String> {
private final String keyPrefix = "test:";
private final String charsetName = "UTF-8";
private Charset charset;
@Override
public byte[] serialize(String key) throws SerializationException {
String builderKey = keyPrefix + key;
return builderKey.getBytes();
}
@Override
public String deserialize(byte[] bytes) throws SerializationException {
return new String(bytes, charset);
}
@Override
public void afterPropertiesSet() throws Exception {
charset = Charset.forName(charsetName);
}
}
- 注意:实现
InitializingBean
会让RedisKeySerializer
在注册到Spring
容器时初始化相关的Charset
字符集
配置 RedisConfig
1、为了解决 RedisTemplate<K , V>
在操作时的序列化器问题,需要把 setKeySerializer
设置成 RedisKeySerializer
如果不设置会把 K 进行序列化后在进行相关的存储操作,此时 K 就是 K 序列化后的值
2、配置 Redis
序列化器添加之前我们配置的 ObjectMapper
对象从而解决 1、配置查询缓存转换异常;2、JSON转化为对象,会转化成Map类型 两个问题
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
// 创建模板
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 设置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 设置序列化工具
//
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// // key和 hashKey采用 string序列化
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
redisTemplate.setKeySerializer(new RedisKeySerializer());
redisTemplate.setHashKeySerializer(new RedisKeySerializer());
// // value和 hashValue采用 JSON序列化
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
- StringRedisTemplate
@Bean(name = "stringStringRedisTemplate")
public StringRedisTemplate stringStringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
stringRedisTemplate.setKeySerializer(new RedisKeySerializer());
stringRedisTemplate.setHashKeySerializer(new RedisKeySerializer());
stringRedisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
stringRedisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
stringRedisTemplate.afterPropertiesSet();
return stringRedisTemplate;
}
注意事项
1、StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。
2、RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。
3、两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。
4、操作简单的数据可以采用 StringRedisTemplate
可以减少序列化的开销,操作复杂的数据类型时可以采用 RedisTemplate
5、StringRedisTemplate
存储非基本类型时需要把 class
转换成 JSONString
User user = new User();
user.setAge(20);
user.setName("231213");
user.setDateTime(LocalDateTime.now());
String key = StrUtil.builder().append(RedisConstants.USER_PREFIX).append(user.getName()).toString();
stringRedisTemplate.opsForValue().set(key ,JSONUtil.toJsonStr(user));
6、获取时如果获取的是非基本类型数据需要通过 FASTJSON2
的 JSON.parseObject(vaue , clazz); 进行对象转换