Java 为spring boot redis缓存配置新的序列化程序

Java 为spring boot redis缓存配置新的序列化程序,java,spring-boot,caching,redis,spring-data-redis,Java,Spring Boot,Caching,Redis,Spring Data Redis,我一直在尝试更改spring boot redis缓存的默认序列化程序,因为我想将默认序列化程序更改为Jackson2Json实现之一。Jackson2Json库中有两个实现,其中一个是:GenericJackson2JsonRedisSerializer,我可以在以下bean实例化中使用它: @Bean @Primary public RedisCacheConfiguration defaultCacheConfig(ObjectMapper objectMapper) { ret

我一直在尝试更改spring boot redis缓存的默认序列化程序,因为我想将默认序列化程序更改为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,我如何告诉他如何转换

我尝试使用的另一个序列化程序是Jackson2JSONRedisalizer:

@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("");
}
@Bean
@初级的
公共RedisCacheConfiguration defaultCacheConfig(ObjectMapper ObjectMapper){
Jackson2JsonRedisSerializer serializer=新的Jackson2JsonRedisSerializer(Person.class);
serializer.setObjectMapper(objectMapper);
返回RedisCacheConfiguration.defaultCacheConfig()
.与(
SerializationPair.fromSerializer(
新的StringRedisSerializer()
)
)
.将值序列化为(
SerializationPair.fromSerializer(
序列化程序
)
)
.前缀为(“”);
}
这样,我必须为保存在redis缓存上的每个对象声明一个bean,但我可以正确地序列化/反序列化

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


如果有什么方法可以改进我的问题,请告诉我。

GenericJackson2JsonRedisSerializer
采用Jackson的方法。使用
ObjectMapper
实例创建
GenericJackson2JSONRedisializer
时,请确保配置默认类型(
enableDefaultTyping(…)

默认类型最适用于非final类型,并且需要在所有JSON负载中为该类型提供一致的属性名,以便Jackson能够识别要反序列化的适当类型

默认类型使用动态类型标记,如果您的数据源(Redis实例)不完全受信任,那么这可能会成为一个安全问题


Jackson2JsonRedisSerializer
被固定到特定类型,消除了动态键入风险。

我知道问题提出已经很久了,但可能还有人需要答案

我遇到了同样的问题,我使用
JdkSerializationRedisSerializer
而不是
GenericJackson2JsonRedisSerializer
解决了这个问题

我的
RedisCacheConfiguration
bean看起来像:

return RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofHours("your-long-value"))
            .serializeKeysWith(SerializationPair.fromSerializer(new StringRedisSerializer()))
            .serializeValuesWith(SerializationPair.fromSerializer(new JdkSerializationRedisSerializer())); 

您可以使用SpringDataRedis

添加依赖项:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

org.springframework.boot
spring引导启动器数据jpa
org.springframework.boot
SpringBootStarterWeb
org.springframework.boot
spring启动程序数据redis
启用缓存并使用Jackson2JsonRedisSerializer

package 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
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(objectMapper);
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(serializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
        return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
    }
}
包com.redis.demo.redisdemo.config;
导入com.fasterxml.jackson.annotation.jsonautodect;
导入com.fasterxml.jackson.annotation.PropertyAccessor;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.cache.annotation.CachingConfigurerSupport;
导入org.springframework.cache.annotation.EnableCaching;
导入org.springframework.context.annotation.Bean;
导入org.springframework.context.annotation.Configuration;
导入org.springframework.data.redis.cache.RedisCacheConfiguration;
导入org.springframework.data.redis.cache.RedisCacheManager;
导入org.springframework.data.redis.cache.RedisCacheWriter;
导入org.springframework.data.redis.connection.RedisConnectionFactory;
导入org.springframework.data.redis.core.RedisTemplate;
导入org.springframework.data.redis.serializer.jackson2json重新序列化器;
导入org.springframework.data.redis.serializer.RedisSerializationContext;
导入org.springframework.data.redis.serializer.StringRedisSerializer;
@启用缓存
@配置
公共类RedisConfig扩展了CachingConfigurerSupport{
@自动连线
私有RedisConnectionFactory RedisConnectionFactory;
@豆子
公共RedisTemplate RedisTemplate(RedisConnectionFactory RedisConnectionFactory){
Jackson2JsonRedisSerializer serializer=新的Jackson2JsonRedisSerializer(Object.class);
ObjectMapper ObjectMapper=新的ObjectMapper();
setVisibility(PropertyAccessor.ALL、JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(objectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(objectMapper);
RedisTemplate RedisTemplate=新RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
setKeySerializer(新的StringRedisSerializer());
redisTemplate.setValueSerializer(序列化器);
setHashKeySerializer(新的StringRedisSerializer());
redisTemplate.setHashValueSerializer(序列化程序);
redisTemplate.AfterPropertieSet();
返回模板;
}
@豆子
公共RedisCacheManager RedisCacheManager(RedisTemplate RedisTemplate){
RedisCacheWriter RedisCacheWriter=RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
RedisCacheConfiguration RedisCacheConfiguration=RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer());
返回新的RedisCacheManager(redisCacheWriter、redisCacheConfigu
@Cacheable(value = "employee", key = "#id")
    public Employee getEmployee(Integer id) {
        log.info("Get Employee By Id: {}", id);
        Optional<Employee> employeeOptional = employeeRepository.findById(id);
        if (!employeeOptional.isPresent()) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Id Not foud");
        }
        return employeeOptional.get();
    }