springboot2.x使用redis做缓存

时间:2022-12-30 22:10:05

1.springboot使用 redis 做缓存之后我们有两种操作缓存的方式:

    (1)使用注解来操作缓存,我们常用的注解有

      @Cacheable:主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

      @CacheEvict:清空缓存

      @CachePut:保证方法被调用,又希望结果被缓存

      .....

      我们可以通过自定义缓存管理器(CacheManager)来统一基于注解的缓存规则,对缓存管理器的一些设置(全局过期时间等)都会反映到缓存管理器管理的所有缓存上;具体的配置方式跟1.0也有所不同,在1.0中使用RedisTemplate即可实例化一个RedisCacheManager:RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);,在2.0中删除了这个构造器,在2.0中可以通过Spring提供的RedisCacheConfiguration类构造一个RedisCacheManager,从该配置类中可以设置一些初始化的缓存命名空间、及对应的默认过期时间等属性,再利用RedisCacheManager中的builder.build()的方式生成cacheManager:看代码

@Configuration
public class RedisCacheManagerConfig {

@Value("${cache.default.expire-time:1800}")
private int defaultExpireTime;
@Value("${cache.test.expire-time:180}")
private int testExpireTime;
@Value("${cache.test.name:test}")
private String testCacheName;

//缓存管理器
@Bean
public CacheManager cacheManager(RedisConnectionFactory lettuceConnectionFactory) {
// 生成一个默认配置,通过config对象即可对缓存进行自定义配置
RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
// 设置缓存管理器管理的缓存的默认过期时间
defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofSeconds(defaultExpireTime))
// 设置 key为string序列化
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
// 设置value为json序列化
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
// 不缓存空值
.disableCachingNullValues();
// 设置一个初始化的缓存空间set集合
Set<String> cacheNames= new HashSet<>();
cacheNames.add(testCacheName);

// 对每个缓存空间应用不同的配置
Map<String,RedisCacheConfiguration> configMap = new HashMap<>();
configMap.put(testCacheName,defaultCacheConfig.entryTtl(Duration.ofSeconds(testExpireTime)));

// 使用自定义的缓存配置初始化一个cacheManager
RedisCacheManager cacheManager = RedisCacheManager.builder(lettuceConnectionFactory)
.cacheDefaults(defaultCacheConfig)
// 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
.initialCacheNames(cacheNames)
.withInitialCacheConfigurations(configMap)
.build();
return cacheManager;
}
}
使用实例
@Override
@Cacheable(cacheNames = {"product"})// 不设置缓存组件的名字就会报 No cache could be resolved for 'Builder 异常
public Product getProductByProductId(String productId) {
return productMapper.findByProductId(productId);
}

    (2).使用 RedisTemplate 和  StringRedisTemplate 来操作缓存

      使用 RedisTemplate 或 StringRedisTemplate 来操作缓存其实与我们通过redis-cli操作缓存是一样的,这里需要注意的一点是:这两个 templeate 不受缓存管理器(

CacheManager)管理,所以上面(1)中配置的 CacheManager 对于RedisTemplate 和 StringRedisTemplate 是不起作用的,看代码
@Test
public void testObjectRedis(){
Product product = productMapper.findByProductId("b236b4c8656911e9a662707781a2dbac");
// 在 redis 中保存对象,默认使用 jdk 序列化机制,序列化后的数据保存到 redis 中。
redisTemplate.opsForValue().set(product.getProductId(),product);
}
如果想自定义 Template ,我们可以在容器中加入自定义的 template,并配置相应的缓存规则。
@Configuration
public class RedisConfig {


@Bean
public RedisTemplate<Object, Product> productRedisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<Object,Product> template = new RedisTemplate<Object, Product>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Product> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Product>(Product.class);
template.setDefaultSerializer(jackson2JsonRedisSerializer);// key 和 value 都会用到这个序列化器
return template;
}

@Bean
public RedisTemplate<Object, ProductDTO> productDTORedisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<Object,ProductDTO> template = new RedisTemplate<Object, ProductDTO>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<ProductDTO> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<ProductDTO>(ProductDTO.class);
template.setDefaultSerializer(jackson2JsonRedisSerializer);
return template;
}
}
使用自定义的 template 来操作缓存
@Autowired
private RedisTemplate<Object,Product> productRedisTemplate;
// 测试保存对象
@Test
public void testObjectRedis(){
Product product = productMapper.findByProductId("b236b4c8656911e9a662707781a2dbac");
productRedisTemplate.opsForValue().set(product.getProductId(),product);
}