为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

温温酱 2022-07-27 20:59:32
我一直在尝试更改 spring-boot redis 缓存的默认序列化程序,因为我想从 Default 更改为 Jackson2Json 实现之一。Jackson2Json 库中有两个实现,其中之一是:GenericJackson2JsonRedisSerializer,我可以在以下 bean 实例化中使用它:@Bean@Primarypublic 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 causejava.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@Primarypublic 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 属性为空。有没有办法来解决这个问题?如果有办法改善我的问题,请告诉我。
查看完整描述

3 回答

?
红糖糍粑

TA贡献1815条经验 获得超6个赞

GenericJackson2JsonRedisSerializer假设杰克逊的默认类型。当您GenericJackson2JsonRedisSerializer使用ObjectMapper实例创建时,请确保配置默认类型 ( enableDefaultTyping(…))。

默认类型最适合非最终类型,并且需要在所有 JSON 有效负载中为类型提供一致的属性名称,以便 Jackson 可以识别要反序列化的适当类型。

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

Jackson2JsonRedisSerializer固定到特定类型并消除动态类型风险。


查看完整回答
反对 回复 2022-07-27
?
斯蒂芬大帝

TA贡献1827条经验 获得超8个赞

您可以使用 Spring Data Redis


添加依赖项:


<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>

启用缓存和使用 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);

    }

}

在方法中添加可缓存注释以缓存在redis中


@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();

    }


查看完整回答
反对 回复 2022-07-27
?
眼眸繁星

TA贡献1873条经验 获得超9个赞

我知道这个问题被问到已经很久了,但可能还有人需要答案。

我有同样的问题,我使用JdkSerializationRedisSerializer而不是解决它GenericJackson2JsonRedisSerializer

我的RedisCacheConfiguration豆子看起来像:

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



查看完整回答
反对 回复 2022-07-27
  • 3 回答
  • 0 关注
  • 195 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号