You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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注解配置,按以下步骤调整:

  1. 移除全局默认类型激活配置
    删除Jackson2JsonRedisSerializer配置中的这段代码:

    objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
    

    该配置会全局强制多态类型处理规则,和你在A类上定义的btType规则冲突。

  2. 指定序列化器的目标类型为抽象类A
    因为@Cacheable默认将缓存值视为Object类型,Jackson无法自动识别A类的多态注解,所以需要明确序列化目标类型:

    // 初始化序列化器时指定目标类型为抽象类A
    Jackson2JsonRedisSerializer<A> serializer = new Jackson2JsonRedisSerializer<>(A.class);
    serializer.setObjectMapper(objectMapper);
    

    这样Jackson会使用A类上的@JsonTypeInfo、@JsonSubTypes注解处理多态,序列化生成btType字段,反序列化时也会依据该字段识别子类。

  3. 配置RedisCacheManager使用自定义序列化器
    在构建RedisCacheManager时,将上述序列化器绑定到缓存配置:

    RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer));
    RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
            .cacheDefaults(cacheConfig)
            .build();
    

    确保所有缓存A及其子类的操作都使用该配置。

  4. 多类型缓存的适配(可选)
    若需要缓存多种不同类型的对象,可为特定缓存名称单独配置序列化器:

    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 08:32:44