为 spring-boot redis 缓存配置配置一个新的序列化程序

我一直在尝试更改 spring-boot redis 缓存的默认序列化程序,因为我想从 Default 更改为 Jackson2Json 实现之一。Jackson2Json 库中有两个实现,其中之一是:GenericJackson2JsonRedisSerializer,我可以在以下 bean 实例化中使用它:


@Bean

@Primary

public RedisCacheConfiguration defaultCacheConfig(ObjectMapper objectMapper) {


    return RedisCacheConfiguration.defaultCacheConfig()

        .serializeKeysWith(

            SerializationPair.fromSerializer(

                new StringRedisSerializer()

            )

        )

        .serializeValuesWith(

            SerializationPair.fromSerializer(

                new GenericJackson2JsonRedisSerializer(objectMapper)

            )

        )

        .prefixKeysWith("");

}

当我使用此序列化程序时,序列化工作正常,所有内容都存储在 redis 服务器上,但是当我尝试反序列化存储在 redis 服务器上的 JSON 时,我收到以下异常:


java.util.LinkedHashMap cannot be cast to tutorial.Person with root cause


java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to tutorial.Person

缓存的使用方式如下:


@Cacheable(cacheNames = "person", key = "'person:'.concat(#post.id)")

public Person findPostAuthor(Post post){

}

序列化程序不知道如何从 LinkedHashMap 转换为 Person,我怎么能告诉他怎么做呢?


我尝试使用的另一个序列化器是 Jackson2JsonRedisSerializer:


@Bean

@Primary

public RedisCacheConfiguration defaultCacheConfig(ObjectMapper objectMapper) {

    Jackson2JsonRedisSerializer<Person> serializer = new Jackson2JsonRedisSerializer<>(Person.class);

    serializer.setObjectMapper(objectMapper);

    return RedisCacheConfiguration.defaultCacheConfig()

        .serializeKeysWith(

            SerializationPair.fromSerializer(

                new StringRedisSerializer()

            )

        )

        .serializeValuesWith(

            SerializationPair.fromSerializer(

                serializer

            )

        )

        .prefixKeysWith("");

}

这样,我必须为保存在 redis 缓存中的每个对象声明一个 bean,但我可以正确序列化/反序列化。


当我直接在 redis 缓存中插入 JSON 时,我无法使用此序列化程序对其进行反序列化,序列化程序只会给我一个 Person 对象,其名称、电子邮件和 id 属性为空。有没有办法来解决这个问题?


如果有办法改善我的问题,请告诉我。


温温酱
浏览 196回答 3
3回答

红糖糍粑

GenericJackson2JsonRedisSerializer假设杰克逊的默认类型。当您GenericJackson2JsonRedisSerializer使用ObjectMapper实例创建时,请确保配置默认类型 (&nbsp;enableDefaultTyping(…))。默认类型最适合非最终类型,并且需要在所有 JSON 有效负载中为类型提供一致的属性名称,以便 Jackson 可以识别要反序列化的适当类型。默认类型使用动态类型标记,如果您的数据源(Redis 实例)不完全受信任,那么这可能会成为安全问题。Jackson2JsonRedisSerializer固定到特定类型并消除动态类型风险。

斯蒂芬大帝

您可以使用 Spring Data Redis添加依赖项:<dependency>&nbsp; <groupId>org.springframework.boot</groupId>&nbsp; <artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency>&nbsp; <groupId>org.springframework.boot</groupId>&nbsp; <artifactId>spring-boot-starter-web</artifactId></dependency><dependency>&nbsp; <groupId>org.springframework.boot</groupId>&nbsp; <artifactId>spring-boot-starter-data-redis</artifactId></dependency>启用缓存和使用 Jackson2JsonRedisSerializerpackage com.redis.demo.redisdemo.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.annotation.CachingConfigurerSupport;import org.springframework.cache.annotation.EnableCaching;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheConfiguration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.cache.RedisCacheWriter;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.RedisSerializationContext;import org.springframework.data.redis.serializer.StringRedisSerializer;@EnableCaching@Configurationpublic class RedisConfig extends CachingConfigurerSupport {&nbsp; &nbsp; @Autowired&nbsp; &nbsp; private RedisConnectionFactory redisConnectionFactory;&nbsp; &nbsp; @Bean&nbsp; &nbsp; public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {&nbsp; &nbsp; &nbsp; &nbsp; Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);&nbsp; &nbsp; &nbsp; &nbsp; ObjectMapper objectMapper = new ObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp; objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);&nbsp; &nbsp; &nbsp; &nbsp; objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);&nbsp; &nbsp; &nbsp; &nbsp; serializer.setObjectMapper(objectMapper);&nbsp; &nbsp; &nbsp; &nbsp; RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();&nbsp; &nbsp; &nbsp; &nbsp; redisTemplate.setConnectionFactory(redisConnectionFactory);&nbsp; &nbsp; &nbsp; &nbsp; redisTemplate.setKeySerializer(new StringRedisSerializer());&nbsp; &nbsp; &nbsp; &nbsp; redisTemplate.setValueSerializer(serializer);&nbsp; &nbsp; &nbsp; &nbsp; redisTemplate.setHashKeySerializer(new StringRedisSerializer());&nbsp; &nbsp; &nbsp; &nbsp; redisTemplate.setHashValueSerializer(serializer);&nbsp; &nbsp; &nbsp; &nbsp; redisTemplate.afterPropertiesSet();&nbsp; &nbsp; &nbsp; &nbsp; return redisTemplate;&nbsp; &nbsp; }&nbsp; &nbsp; @Bean&nbsp; &nbsp; public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {&nbsp; &nbsp; &nbsp; &nbsp; RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());&nbsp; &nbsp; &nbsp; &nbsp; RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));&nbsp; &nbsp; &nbsp; &nbsp; return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);&nbsp; &nbsp; }}在方法中添加可缓存注释以缓存在redis中@Cacheable(value = "employee", key = "#id")&nbsp; &nbsp; public Employee getEmployee(Integer id) {&nbsp; &nbsp; &nbsp; &nbsp; log.info("Get Employee By Id: {}", id);&nbsp; &nbsp; &nbsp; &nbsp; Optional<Employee> employeeOptional = employeeRepository.findById(id);&nbsp; &nbsp; &nbsp; &nbsp; if (!employeeOptional.isPresent()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Id Not foud");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return employeeOptional.get();&nbsp; &nbsp; }

眼眸繁星

我知道这个问题被问到已经很久了,但可能还有人需要答案。我有同样的问题,我使用JdkSerializationRedisSerializer而不是解决它GenericJackson2JsonRedisSerializer。我的RedisCacheConfiguration豆子看起来像:return&nbsp;RedisCacheConfiguration.defaultCacheConfig() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.entryTtl(Duration.ofHours("your-long-value")) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.serializeKeysWith(SerializationPair.fromSerializer(new&nbsp;StringRedisSerializer())) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.serializeValuesWith(SerializationPair.fromSerializer(new&nbsp;JdkSerializationRedisSerializer()));
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java