SpringBoot2.3.0自定义RedisCacheManager并对缓存Jackson序列化

版本:

  • spring-boot:2.3.0
  • redis:latest(Docker)

依赖

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

application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/spring_boot?serverTimezone=GMT%2B8
    type: com.mysql.cj.jdbc.MysqlDataSource

  jpa:
    show-sql: true
    database: mysql
    hibernate:
      ddl-auto: update

  redis:
    host: 127.0.0.1
  cache:
    redis:
      use-key-prefix: true

在spring-boot2.x之前

RedisCacheManager cacheManager = new RedisCacheManager(RedisTemplate redisTemplate);

spring-boot2.0后

RedisCacheManager cacheManager = new RedisCacheManager(RedisCacheWriter redisCacheWriter,RedisCacheConfiguration redisCacheConfiguration);

步骤:

  • 开始:

    写一个配置类

    • 给容器注册一个Bean,返回缓存管理器
    • 这里redisTemplate容器中有,所以会自动注入
    @Configuration
    public class CustomizeRedisCacheManager {
    
        @Bean
        public CacheManager customizeCacheManager(RedisTemplate redisTemplate) {
        
        }
    
    }
    
  • 第一步:

    创建RedisCacheWriter

    • nonLockingRedisCacheWriter(RedisConnectionFactory connectionFactory);
      • 非锁
    • lockingRedisCacheWriter(RedisConnectionFactory connectionFactory);
      • 有锁
    RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
    
  • 第二步:

    创建Jackson对象并传入需要序列化的对象

    Jackson2JsonRedisSerializer<RedisUser> serializer = new Jackson2JsonRedisSerializer<>(RedisUser.class);
    
  • 第三步:

    传入 Jackson对象 并获取 RedisSerializationContext对象

    RedisSerializationContext<RedisUser, RedisUser> serializationContext = RedisSerializationContext.fromSerializer(serializer);
    
  • 第四步:

    配置RedisCacheConfiguration

    • RedisCacheConfiguration.defaultCacheConfig()
      • serializeValuesWit(SerializationPari<?> valueSerializationPari)
        • 设置 value 的序列化
      • serializeKeysWith(SerializationPari valueSerializationPari)
        • 设置 key 的序列化
    RedisCacheConfiguration redisCacheConfiguration =  RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(serializationContext.getValueSerializationPair());
    

    经测试:如果用如下配置无效

    RedisSerializationContext.SerializationPair<RedisUser> redisUserSerializationPair = RedisSerializationContext.SerializationPair.fromSerializer(serializer);
    
  • 最后一步:

    创建RedisCacheManager(RedisCacheWriter redisCacheWriter, RedisCacheConfiguration redisCacheConfiguration)对象并返回

    return new RedisCacheManager(redisCacheWriter,redisCacheConfiguration);
    

完整示例

package com.live.config;

import com.live.model.RedisUser;
import org.springframework.cache.CacheManager;
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.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.util.Objects;

@Configuration
public class CustomizeRedisCacheManager {

    @Bean
    public CacheManager customizeCacheManager(RedisTemplate redisTemplate) {
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(Objects.requireNonNull(redisTemplate.getConnectionFactory()));

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

        RedisSerializationContext<RedisUser, RedisUser> serializationContext = RedisSerializationContext.fromSerializer(serializer);
        RedisCacheConfiguration redisCacheConfiguration =  RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(serializationContext.getValueSerializationPair());

        return new RedisCacheManager(redisCacheWriter,redisCacheConfiguration);
    }

}

一步写完是这个样子的,哈哈

@Bean(name = "myCacheManager")
public CacheManager customizerRedisCacheManager(RedisTemplate redisTemplate) {
    return new RedisCacheManager(
            RedisCacheWriter
                    .nonLockingRedisCacheWriter(Objects
                            .requireNonNull(redisTemplate
                                    .getConnectionFactory())),
            RedisCacheConfiguration
                    .defaultCacheConfig()
                    .serializeValuesWith(
                            RedisSerializationContext
                                    .fromSerializer(new Jackson2JsonRedisSerializer<>(RedisUser.class))
                                    .getValueSerializationPair()));
}

对结果缓存

  • @Cacheable(cacheNames = “redisUser”, key = “#id”, cacheManager = “customizeCacheManager”)
    cacheManager指定我们自定义的RedisCacheManager

这里注意: 如果使用的JPA,不要使用findById(id).get() 来返回对象;会反序列化失败

@Service
public class RedisUserService {

    @Autowired
    JPARepository jpaRepository;

    @Cacheable(cacheNames = "redisUser", key = "#id", cacheManager = "customizeCacheManager")
    public Optional<RedisUser> findOneById(Integer id) {
        return jpaRepository.findById(id);
    }

}

效果:成功对缓存json序列化

在这里插入图片描述

其它代码(Model、Repository、Service、Controller)

Model

package com.live.model;

import lombok.Data;

import javax.persistence.*;
import java.io.Serializable;

@Data
@Entity
@Table(name = "redis_user")
public class RedisUser implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "redis_name",length = 100,unique = true)
    private String name;
    @Column(name = "redis_password", length = 125, nullable = false)
    private String password;

}

Repository

import com.live.model.RedisUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface JPARepository extends JpaRepository<RedisUser,Integer> {}

Service

@Service
public class RedisUserService {

    @Autowired
    JPARepository jpaRepository;

    @Cacheable(cacheNames = "redisUser", key = "#id", cacheManager = "customizeCacheManager")
    public Optional<RedisUser> findOneById(Integer id) {
        return jpaRepository.findById(id);
    }

}

Controller

package com.live.controller;

import com.live.model.RedisUser;
import com.live.service.RedisUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.Optional;

@RestController
public class RedisController {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RedisUserService redisUserService;

    @GetMapping("/redis/findOne/{id}")
    public Optional<RedisUser> findOneById(@PathVariable(value = "id") Integer id) {
        return redisUserService.findOneById(id);
    }

}

版权声明:本文为weixin_44216706原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。