文章目录
正文
一、导入依赖
这里使用jackson依赖,用其他的序列化工具也可
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
二、创建RedisTemplate的配置类
1. 基础配置
@Configuration
public class RedisTemplateConfig {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 创建redisTemplate对象
RedisTemplate<Object, Object> template = new RedisTemplate<>();
// 连接工厂
template.setConnectionFactory(redisConnectionFactory);
// 获取序列化工具
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// 设置key的序列化 (Redis 默认序列化工具)
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
// 设置value的序列化 (Jackson 序列化工具)
template.setValueSerializer(jsonRedisSerializer);
template.setHashValueSerializer(jsonRedisSerializer);
// 开启事务
template.setEnableTransactionSupport(true);
return template;
}
}
上述配置就可以满足基本需求,但当java实体类含有LocalDateTime数据类型时会报错:org.springframework.data.redis.serializer.SerializationException: Could not write JSON: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module
因此需要配置序列化工具,使其支持对该数据类型的序列化与反序列化
2. 配置序列化工具,解决LocalDateTime序列化问题
private GenericJackson2JsonRedisSerializer myJasonRedisSerializer() {
ObjectMapper objectMapper = new ObjectMapper();
// 设置可见性
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 序列化后添加类信息(不配置,序列化后就是一个Json字符串)
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
// 将日期序列化为可读字符串而不是时间戳
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
//设置时间模块(格式化,不设置,则输出默认格式)
JavaTimeModule timeModule = new JavaTimeModule();
// LocalDateTime
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.of("Asia/Shanghai"))));
timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.of("Asia/Shanghai"))));
// LocalDate
timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.of("Asia/Shanghai"))));
timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.of("Asia/Shanghai"))));
// 设置自定义时间模块
objectMapper.registerModule(timeModule);
return new GenericJackson2JsonRedisSerializer(objectMapper);
}
注:
1. objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); 会在序列化后带上类的信息,便于反序列化。
2. 解决序列化LocalDateTime数据类型报错:
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.registerModule(new JavaTimeModule());
三、完整代码
代码如下:
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
@Configuration
public class RedisTemplateConfig {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 创建redisTemplate对象
RedisTemplate<Object, Object> template = new RedisTemplate<>();
// 连接工厂
template.setConnectionFactory(redisConnectionFactory);
// 获取序列化工具
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = this.myJasonRedisSerializer();
// 设置key的序列化 (Redis 默认序列化工具)
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
// 设置value的序列化 (Jackson 序列化工具)
template.setValueSerializer(jsonRedisSerializer);
template.setHashValueSerializer(jsonRedisSerializer);
// 开启事务
template.setEnableTransactionSupport(true);
return template;
}
private Jackson2JsonRedisSerializer<Object> myJasonRedisSerializer() {
ObjectMapper objectMapper = new ObjectMapper();
// 设置可见性
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 序列化后添加类信息(不配置,序列化后就是一个Json字符串)
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
// 将日期序列化为可读字符串而不是时间戳
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 设置时间模块(格式化,不设置,则输出默认格式)
JavaTimeModule timeModule = new JavaTimeModule();
// LocalDateTime
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.of("Asia/Shanghai"))));
timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.of("Asia/Shanghai"))));
// LocalDate
timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.of("Asia/Shanghai"))));
timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.of("Asia/Shanghai"))));
// 设置自定义时间模块
objectMapper.registerModule(timeModule);
return new Jackson2JsonRedisSerializer<>(objectMapper, Object.class);
}
}
四、无法自动装配解决办法
写好配置,但在写项目时却遇到了:无法自动装配,找不到 'RedisTemplate<Object, String>' 类型的 Bean的报错问题,通过查阅资料(秋日的晚霞 - springboot整合redisTemplate 自动装配失败原因)找到了解决办法:
如果使用 @Autowired(按类型装配) 进行自动装配,那么RedisTemplate就不要指定泛型,或者将泛型指定为<Stirng,String> 或者<Object,Object>;(我就在这卡了很久。。)
而如果想要指定泛型例如<String,Object>,那么就需要使用 @Resource(按bean名称装配) 来进行自动装配。