当前位置: 首页 > 工具软件 > CacheManager > 使用案例 >

Redis缓存的使用和基于SpringBoot1.x和SpringBoot2.x的RedisCacheManager配置使用详解

路和悌
2023-12-01

     * Redis是一个开源的,内存中的数据机构存储系统,它可以作为数据库,缓存和消息中间件。
     * 使用:安装redis,引入redis的starter,配置redis
     * 原理:CacheManager == Cache 缓存组件来实际给缓存中存取数据,替换默认的SimpleCacheConfiguration
     *      1.引入redis的starter,容器中保存的是RedisCacheManager
     *      2.RedisCacheManager 底层帮我们创建RedisCache来作为缓存组件:RedisCache通过操作redis缓存数据的
     *      3.默认保存数据 k-v 都是Object,利用序列化保存的(需转换json)
     *      附 SimpleCacheConfiguration和RedisCacheConfiguration 底层配置对比:
     *          @Configuration(proxyBeanMethods = false)
     *          @ConditionalOnMissingBean({CacheManager.class})  //SimpleCacheConfiguration起作用是容器中没有CacheManager
     *          @Conditional({CacheCondition.class})
     *          class SimpleCacheConfiguration {}
     *
     *          @Configuration(proxyBeanMethods = false)
     *          @ConditionalOnClass({RedisConnectionFactory.class})
     *          @AutoConfigureAfter({RedisAutoConfiguration.class})
     *          @ConditionalOnBean({RedisConnectionFactory.class})
     *          @ConditionalOnMissingBean({CacheManager.class})  //redis也需要判断容器中没有CacheManager才生效
     *          @Conditional({CacheCondition.class})
     *          class RedisCacheConfiguration {}
     * 原因:
     *      1.引入redis的starter,cacheManager变为RedisCacheManager,剩下的CacheManager就不起作用了
     *      2.默认创建的RedisCacheManager操作redis的时候使用的是RedisTemplate<Object,Object>
     *      3.RedisTemplate<Obejct,Object>是默认使用【jdk的序列化机制】
     *      4.自定义CacheManager在MyRedisConfig中

     * 使用:
     *         常用类型:String list(列表) Set(集合) Hash(散列) ZSet(有序集合)
     *          stringRedisTemplate.opsForValue();
     *          stringRedisTemplate.opsForList();
     *          stringRedisTemplate.opsForSet();
     *          stringRedisTemplate.opsForHash();
     *          stringRedisTemplate.opsForZSet();

导入坐标(版本根据springboot走):

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>

配置文件:

spring.redis.host=localhost
spring.cache.redis.use-key-prefix=true  #使用CacheName作为key的前缀

基于Springboot1.x配置RedisCacheManager

import com.bootbootboot.springboot01cache.bean.Department;
import com.bootbootboot.springboot01cache.bean.Employee;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

/**
 * springboot 1.X 版本RedisCacheManager配置
 */
@Configuration
public class MyRedisConfig {

    @Bean
    //@ConditionalOnMissingBean
    public RedisTemplate<Object, Employee> empRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
        template.setConnectionFactory(redisConnectionFactory);
        //获取jackson序列化器
        Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
        //设置序列化器
        template.setDefaultSerializer(ser);
        return template;
    }

    @Bean
    public RedisTemplate<Object, Department> deptRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Department> template = new RedisTemplate<Object, Department>();
        template.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer<Department> ser = new Jackson2JsonRedisSerializer<Department>(Department.class);
        template.setDefaultSerializer(ser);
        return template;
    }

    /**
     * 这里可以扩展使用自定义的RedisTemplate<Object,Object>自定义缓存
     */
    //CacheManagerCustomizers可以来定制缓存的一些规则
    @Primary  //将某个管理器设为默认
    @Bean
    public RedisCacheManager employeeCacheManager(RedisTemplate<Object, Employee> empRedisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(empRedisTemplate);
        //使用CacheName作为key的前缀,可在application配置文件中开启
        //cacheManager.setUserPrefix(true);
        return cacheManager;
    }

    @Bean
    public RedisCacheManager deptCacheManager(RedisTemplate<Object, Department> deptRedisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(deptRedisTemplate);
        //cacheManager.setUserPrefix(true);
        return cacheManager;
    }

}

基于Springboot2.x配置RedisCacheManager

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.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.time.Duration;
import java.util.Objects;

/**
 * springboot 2.X 版本的RedisManager配置
 * 注意:
 *      在配置文件中使用CacheName作为key的前缀:spring.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);
 */
@Configuration
public class MyRedisCacheConfig {

    //spring-boot2.x之前
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(1))
                .disableCachingNullValues()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();
    }

    //spring-boot2.0之后
    @Bean  //给容器注册一个Bean,返回缓存管理器,这里redisTemplate容器中有,所以会自动注入
    public CacheManager MyRedisCacheConfig(RedisTemplate redisTemplate) {
        //1.创建RedisCacheWriter
        /**
         * 非锁方式:nonLockingRedisCacheWriter(RedisConnectionFactory connectionFactory);
         * 有锁方式:lockingRedisCacheWriter(RedisConnectionFactory connectionFactory);
         */
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        //2.创建Jackson对象并传入需要序列化的对象
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        //3.传入 Jackson对象 并获取 RedisSerializationContext对象
        RedisSerializationContext<Object, Object> serializationContext = RedisSerializationContext.fromSerializer(serializer);
        //4.配置RedisCacheConfiguration
        /**
         * RedisCacheConfiguration.defaultCacheConfig()
         * 设置 value 的序列化 serializeValuesWit(SerializationPari<?> valueSerializationPari)
         * 设置 key 的序列化 serializeKeysWith(SerializationPari valueSerializationPari)
         */
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(serializationContext.getValueSerializationPair());
        //5.创建RedisCacheManager(RedisCacheWriter redisCacheWriter, RedisCacheConfiguration redisCacheConfiguration)对象并返回
        return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
    }

    //spring-boot2.0之后简化版
    @Bean(name = "MyRedisCacheManager")
    public CacheManager MyRedisCacheManagerSimple(RedisTemplate redisTemplate) {
        return new RedisCacheManager(
                RedisCacheWriter
                        .nonLockingRedisCacheWriter(Objects
                                .requireNonNull(redisTemplate
                                        .getConnectionFactory())),
                RedisCacheConfiguration
                        .defaultCacheConfig()
                        .serializeValuesWith(
                                RedisSerializationContext
                                        .fromSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class))
                                        .getValueSerializationPair()
                        )
        );
    }
}

使用:

@Service
public class EmployeeServiceForRedisService {

    @Autowired
    private DepartmentMapper departmentMapper;

    @Autowired
    RedisTemplate redisTemplate;  //key-value都是对象

    @Autowired
    RedisTemplate<Object, Employee> empRedisTemplate;  //使用特定对象的redistemplate

    @Qualifier("deptCacheManager")  //使用注解方式指定使用某个缓存管理器
    @Autowired                      //sprintboot 1.x 中配置的CacheManager
    RedisCacheManager deptCacheManager;

    @Qualifier("MyRedisCacheManager")  //springboot 2.x 中配置的CacheManager
    @Autowired
    CacheManager MyRedisCacheConfigSimple;

    /**
     * Redis是一个开源的,内存中的数据机构存储系统,它可以作为数据库,缓存和消息中间件。
     * 使用:安装redis,引入redis的starter,配置redis
     * 原理:CacheManager == Cache 缓存组件来实际给缓存中存取数据,替换默认的SimpleCacheConfiguration
     *      1.引入redis的starter,容器中保存的是RedisCacheManager
     *      2.RedisCacheManager 底层帮我们创建RedisCache来作为缓存组件:RedisCache通过操作redis缓存数据的
     *      3.默认保存数据 k-v 都是Object,利用序列化保存的(需转换json)
     *      附:
     *          @Configuration(proxyBeanMethods = false)
     *          @ConditionalOnMissingBean({CacheManager.class})  //SimpleCacheConfiguration起作用是容器中没有CacheManager
     *          @Conditional({CacheCondition.class})
     *          class SimpleCacheConfiguration {}
     *
     *          @Configuration(proxyBeanMethods = false)
     *          @ConditionalOnClass({RedisConnectionFactory.class})
     *          @AutoConfigureAfter({RedisAutoConfiguration.class})
     *          @ConditionalOnBean({RedisConnectionFactory.class})
     *          @ConditionalOnMissingBean({CacheManager.class})  //redis也需要判断容器中没有CacheManager才生效
     *          @Conditional({CacheCondition.class})
     *          class RedisCacheConfiguration {}
     * 原因:
     *      1.引入redis的starter,cacheManager变为RedisCacheManager,剩下的CacheManager就不起作用了
     *      2.默认创建的RedisCacheManager操作redis的时候使用的是RedisTemplate<Object,Object>
     *      3.RedisTemplate<Obejct,Object>是默认使用【jdk的序列化机制】
     *      4.自定义CacheManager在MyRedisConfig中
     * 常用类型:String list(列表) Set(集合) Hash(散列) ZSet(有序集合)
     *  stringRedisTemplate.opsForValue();
     *  stringRedisTemplate.opsForList();
     *  stringRedisTemplate.opsForSet();
     *  stringRedisTemplate.opsForHash();
     *  stringRedisTemplate.opsForZSet();
     */

    public void saveStringType() {
        //保存数据
        stringRedisTemplate.opsForValue().append("msg", "hello");
        stringRedisTemplate.opsForList().leftPush("myList", "2");
        //读取数据
        String msg = stringRedisTemplate.opsForValue().get("msg");
    }

    public void saveBeanType() {
        Employee empById = employeeMapper.getEmpById(1);
        //默认如果保存对象(对象需实现Serializable接口),使用jdk序列化机制,序列化后的数据保存到redis中
        redisTemplate.opsForValue().set("emp-01", empById);
        /**
         * 将数据以json方式保存
         *  1.自己将对象转为json
         *  2.redisTemplate实现自己的序列化机制
         */
        empRedisTemplate.opsForValue().set("emp-01", empById);
    }

    /**
     * 使用配置缓存
     * 注意:
     *      如果使用的JPA,不要使用findById(id).get() 来返回对象;会反序列化失败。
     */
    @Cacheable(cacheNames = "dept",key = "#id", cacheManager = "deptCacheManager")  //springboot 1.X
//    @Cacheable(cacheNames = "dept",key = "#id", cacheManager = "MyRedisCacheConfig")  //springboot 2.X
    public Department getDeptById(Integer id) {
        Department department = departmentMapper.getDeptById(id);
        return department;
    }

    /**
     * 使用缓存管理器得到缓存:
     *     @Qualifier("deptCacheManager")  //指定使用某个缓存管理器
     *     @Autowired
     *     RedisCacheManager deptCacheManager;
     */
    public Department getDeptById2(Integer id) {
        Department department = departmentMapper.getDeptById(id);
        //获取某个缓存
        Cache dept = deptCacheManager.getCache("dept");
        dept.put("dept:1", department);
        return department;
    }
}

 类似资料: