如何让RedisCacheManager默认使用POJO上的Jackson注解适配@Cacheable
问题
我有一个类继承体系,B和C继承抽象类A。在A中我使用标准Jackson注解处理多态结构的序列化与反序列化:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "btType") // btType because we have a type field @JsonIgnoreProperties(value = "btType", allowSetters = true) @JsonSubTypes({@JsonSubTypes.Type(value = B.class, name = "B")}) public abstract class A{}
此前使用RedisTemplate时,Jackson可成功添加btType字段,完成B、C实例的序列化与反序列化。现在需使用@Cacheable抽象,我为RedisCacheManager所用的Jackson2JsonRedisSerializer添加配置:
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
但引入@Cacheable后出现反序列化错误:
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'
发现Jackson不再识别btType而是寻找@class字段,移除POJO上的Jackson注解后恢复正常。请问能否配置RedisCacheManager使其使用POJO上的Jackson注解而非activateDefaultTyping的默认配置?我希望Redis中仍以btType: B而非@class: com.company.whatever.entity.B的形式存储对象,尝试过多种activateDefaultTyping配置均无效。
解决方案
核心问题是全局启用的activateDefaultTyping会覆盖POJO上的注解规则,强制使用@class作为类型标识字段。要让RedisCacheManager优先遵循POJO的Jackson注解配置,按以下步骤调整:
移除全局默认类型激活配置
删除Jackson2JsonRedisSerializer配置中的这段代码:objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);该配置会全局强制多态类型处理规则,和你在A类上定义的
btType规则冲突。指定序列化器的目标类型为抽象类A
因为@Cacheable默认将缓存值视为Object类型,Jackson无法自动识别A类的多态注解,所以需要明确序列化目标类型:// 初始化序列化器时指定目标类型为抽象类A Jackson2JsonRedisSerializer<A> serializer = new Jackson2JsonRedisSerializer<>(A.class); serializer.setObjectMapper(objectMapper);这样Jackson会使用A类上的
@JsonTypeInfo、@JsonSubTypes注解处理多态,序列化生成btType字段,反序列化时也会依据该字段识别子类。配置RedisCacheManager使用自定义序列化器
在构建RedisCacheManager时,将上述序列化器绑定到缓存配置:RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer)); RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(cacheConfig) .build();确保所有缓存A及其子类的操作都使用该配置。
多类型缓存的适配(可选)
若需要缓存多种不同类型的对象,可为特定缓存名称单独配置序列化器:Map<String, RedisCacheConfiguration> cacheConfigs = new HashMap<>(); // 为存储A子类的缓存指定序列化器 cacheConfigs.put("aSubclassCache", RedisCacheConfiguration.defaultCacheConfig() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer))); // 其他缓存可使用默认配置或自定义其他序列化器 RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory) .withInitialCacheConfigurations(cacheConfigs) .build();
调整后,Redis中存储的对象会保留btType: B的格式,@Cacheable也能正常完成序列化与反序列化。
内容的提问来源于stack exchange,提问作者Fabs

