Redis序列化存储及日期格式的问题处理
Redis序列化存储及日期格式的问题处理
·
Redis序列化存储及日期格式的问题处理
项目中突然遇到redis缓存中的实体类日期字段使用LocalDateTime,在Redis序列化时报错,会往Redis中写入如下数据:,导致实体中的时间类型映射不上
"createTime": {
"date": {
"year": 2019,
"month": "MAY",
"day": 15,
"prolepticMonth": 24232,
"era": [
"java.time.chrono.IsoEra",
"CE"
],
"dayOfYear": 135,
"dayOfWeek": "WEDNESDAY",
"leapYear": false,
"dayOfMonth": 15,
"monthValue": 5,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
},
"time": {
"hour": 11,
"minute": 3,
"second": 43,
"nano": 758000000
},
"dayOfYear": 135,
"dayOfWeek": "WEDNESDAY",
"month": "MAY",
"dayOfMonth": 15,
"year": 2019,
"monthValue": 5,
"hour": 11,
"minute": 3,
"second": 43,
"nano": 758000000,
"chronology": [
"java.time.chrono.IsoChronology",
{
"id": "ISO",
"calendarType": "iso8601"
}
]
}
首先来分析下问题出现的原因:
1、项目的RedisConfig中使用的是 ObjectMapper() 来实现对象的序列化和反序列化的,类似与如下代码
@Test
public void test() throws Exception{
EntityDto entityDto = new EntityDto();
entityDto.setCreateTime(LocalDateTime.now());
String s = JSON.toJSONString(entityDto);
ObjectMapper om = new ObjectMapper();
System.out.println("JSON实体类" + s);
System.out.println("JSON实体类" + om.writeValueString(entityDto));
}
输出结果:
可以看到日期类型的值样式被改写了,那修改成原来JSON字符串的格式就需要我们自定义序列化方式
对日期类型数据的序列化:
(这里序列化类型为DateTime,之后时间类型为LocalDate、LocalTime、LocalDateTime、Date都可以用 )
public class JodaDateTimeJsonSerializer extends JsonSerializer<DateTime> {
@Override
public void serialize(DateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(value.toString("yyyy-MM-dd HH:mm:ss"));
}
}
对 DateTime 类型日期的反序列化:
public class JodaDateTimeJsonDeSerializer extends JsonDeserializer<DateTime> {
@Override
public DateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String s = p.readValueAs(String.class);
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
return DateTime.parse(s,dateTimeFormatter);
}
}
添加配置:
// 日期序列化处理
om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
om.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule())
.registerModule(new ParameterNamesModule());
方案一:设置Redis配置文件对日期序列化处理 (推荐)
RedisConfig 完整配置:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 配置连接工厂
template.setConnectionFactory(factory);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// 日期序列化处理
om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
om.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule())
.registerModule(new ParameterNamesModule());
jackson2JsonRedisSerializer.setObjectMapper(om);
// key采用String的序列化方式
template.setKeySerializer(new StringRedisSerializer());
// 值采用Jackson序列化
template.setValueSerializer(jackson2JsonRedisSerializer);
// 设置hash的key采用String序列化模式
template.setHashKeySerializer(new StringRedisSerializer());
// 设置hash的value采用Jackson序列化模式
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
方案二:每个时间类型字段都需要添加,(不推荐,因为太麻烦)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime birthday;
配置好后问题就解决了;
关于ObjectMapper( ) 的用法详情看这里:
Jackson之ObjectMapper对象的使用
更多推荐
已为社区贡献1条内容
所有评论(0)