缓存序列化异常——LocalDateTime
前言
这个问题是我在使用SpringCache进行Redis序列化导致的问题,解决方法分为多个步骤,请大家仔细排查,错误产生方式可能不同
步骤
1.确认序列化
我们首先确认我们要进行序列化的数据,例如如下,我们要确定我们的类要实现Serializable 接口,确保涉及到LocalDateTime的属性必须指定序列化和反序列化的注解,分别为
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
完整示例:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class KnowReposMenuTreeVO implements Serializable {
@JsonSerialize(using = ToStringSerializer.class)
private Long menuId;
private String menuName;
private String url;
private String icon;
private String author;
private Integer orderNum;
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime createTime;
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime updateTime;
private ArrayList<KnowReposMenuTreeVO> child;
}
2.确认数据库连接指定时区与我们序列化时区相同
我们可以看到,我还指定了一个序列化注解@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") ,这里我们指定了timezone也就是时区,指定为东八区!,那么我们的数据库连接时我们也要确保为东八区时间
url: jdbc:mysql://localhost:3306/routerboot_menu?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT+8&zeroDateTimeBehavior=CONVERT_TO_NULL&allowPublicKeyRetrieval=true
或者你可以指定同为Asia/Shanghai 这样指定城市 但这只是一个建议,因为根据我的测试,即使不同也不会影响
3.确认添加依赖
如下使用的是Jaskson序列化时间的依赖,建议加上,但即使加上你可能依然会报错,如果是这样请继续看下去
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
4.更改SpringCache的序列化器
以下代码是自定义的SpringCacheRedisConfig配置,对Redis的序列化键值方式进行修改,键使用了StringRedisSerializer() ,值则使用了GenericFastJsonRedisSerializer() 这是FastJson2的Redis序列化方式,根据我的测试,原先我使用的是GenericJackson2JsonRedisSerializer 性能上比较低,接口首次访问序列化整体时间约3s,修改后平均为700ms,性能提升近5倍
@EnableConfigurationProperties(CacheProperties.class)
@Configuration
@EnableCaching
public class RWRedisConfig {
@Bean
RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericFastJsonRedisSerializer()));
final CacheProperties.Redis redisProperties = cacheProperties.getRedis();
if (redisProperties.getTimeToLive() != null) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
if (redisProperties.getKeyPrefix() != null) {
config = config.prefixCacheNameWith(redisProperties.getKeyPrefix());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}
}
|