Redis缓存Map<Integer, String>

Redis caching Map<Integer, String>

我正在使用 redis 缓存并遇到问题:带有整数键的映射被序列化为字符串,如下所示:

 "1":"AAAA","2":"BBB","3":"CCC"

我的配置是这样的:

@Bean
    public RedisCacheConfiguration myCacheConfiguration()
    {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ZERO)
                .disableCachingNullValues()
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(new Jackson2JsonRedisSerializer<>(Map.class)));
    }

  @Bean
    public CacheManager myCacheManager(RedisConnectionFactory redisConnectionFactory)
    {
        return RedisCacheManager.builder(redisConnectionFactory)
                .cacheDefaults(myCacheConfiguration())
                .transactionAware()
                .build();
    }

我试图将 GenericJackson2JsonRedisSerializer 传递给 serializeValuesWith(),但它不起作用。 有什么方法可以 serialize\deserialize 地图的整数键作为数字吗?

Jackson2JsonRedisSerializerGenericJackson2JsonRedisSerializer 都允许使用自定义 ObjectMapper.

不熟悉 Redis,但似乎是根据 doc:

自定义序列化的设计方式

Setting a custom-configured ObjectMapper is one way to take further control of the JSON serialization process. For example, an extended SerializerFactory can be configured that provides custom serializers for specific types. The other option for refining the serialization process is to use Jackson's provided annotations on the types to be serialized, in which case a custom-configured ObjectMapper is unnecessary.

通过在 Jackson2JsonRedisSerializer 中添加重写方法 JavaType getJavaType(Class clazz) 可以轻松解决该问题。 文档说:

/**
     * Returns the Jackson {@link JavaType} for the specific class.
     * <p>
     * Default implementation returns {@link TypeFactory#constructType(java.lang.reflect.Type)}, but this can be
     * overridden in subclasses, to allow for custom generic collection handling. For instance:
     *
     * <pre class="code">
     * protected JavaType getJavaType(Class&lt;?&gt; clazz) {
     *  if (List.class.isAssignableFrom(clazz)) {
     *      return TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, MyBean.class);
     *  } else {
     *      return super.getJavaType(clazz);
     *  }
     * }
     * </pre>
     *
     * @param clazz the class to return the java type for
     * @return the java type
     */
    protected JavaType getJavaType(Class<?> clazz) {
        return TypeFactory.defaultInstance().constructType(clazz);
    }

所以,我只是像这样覆盖这个方法:

public class CustomSerializer extends Jackson2JsonRedisSerializer
{
    public JurisdictionsSerializer(Class type)
    {
        super(type);
    }


    @Override
    protected JavaType getJavaType(Class clazz)
    {
        return TypeFactory.defaultInstance()
                .constructMapType(Map.class, Integer.class, String.class);
    }
}

然后像这样将这个序列化程序添加到 redis 配置中:

@Bean
    public RedisCacheConfiguration myCacheConfiguration()
    {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ZERO)
                .disableCachingNullValues()
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(new CustomSerializer(Map.class)));
    }