SpringBoot2.x操作缓存的新姿势

 

一、介绍

spring cache 是spring3版本之后引入的一项技术,可以简化对于缓存层的操作,spring cache与springcloud stream类似,都是基于抽象层,可以任意切换其实现。其核心是CacheManagerCache这两个接口,所有由spring整合的cache都要实现这两个接口、Redis的实现类则是 RedisCacheRedisManager。

 

二、使用

Ⅰ、查询

         需要导入的依赖

1 
2     org.springframework.boot
3     spring-boot-starter-cache
4 
5 
6     org.springframework.boot
7     spring-boot-starter-data-redis
8 

   编写对于cache的配置

 1 @EnableCaching
 2 @SpringBootConfiguration
 3 public class CacheConfig {
 4 
 5     @Autowired
 6     private RedisConnectionFactory connectionFactory;
 7 
 8     @Bean // 如果有多个CacheManager的话需要使用@Primary直接指定那个是默认的
 9     public RedisCacheManager cacheManager() {
10         RedisSerializer redisSerializer = new StringRedisSerializer();
11         Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
12 
13         ObjectMapper om = new ObjectMapper();
14         // 防止在序列化的过程中丢失对象的属性
15         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
16         // 开启实体类和json的类型转换
17         om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
18         jackson2JsonRedisSerializer.setObjectMapper(om);
19 
20         // 配置序列化(解决乱码的问题)
21         RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()   .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))             .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
22                 // 不缓存空值
23                 .disableCachingNullValues()
24                 // 1分钟过期
25                 .entryTtl(Duration.ofMinutes(1))
26                 ;
27         RedisCacheManager cacheManager = RedisCacheManager.builder(connectionFactory)
28                 .cacheDefaults(config)
29                 .build();
30         return cacheManager;
31     }
32 } 
  
 

进行以上配置即可使用springboot cache了,还有一个key的生成策略的配置(可选)

 1 @Bean
 2 public KeyGenerator keyGenerator() {
 3     return (target, method, params) -> {
 4         StringBuffer key = new StringBuffer();
 5         key.append(target.getClass().getSimpleName() + "#" + method.getName() + "(");
 6         for (Object args : params) {
 7             key.append(args + ",");
 8         }
 9         key.deleteCharAt(key.length() - 1);
10         key.append(")");
11         return key.toString();
12     };
13 }

注意:如果配置了KeyGenerator ,在进行缓存的时候如果不指定key的话,最后会把生成的key缓存起来,如果同时配置了KeyGenerator 和key则优先使用key。

在controller或者service的类上面添加 @CacheConfig ,注解里面的参数详情见下表:

参数名 参数值 作用
cacheNames 可以随意填写,一般是一个模块或者一个很重要的功能名称 无具体作用,只是用来区分缓存,方便管理
keyGenerator 就是自己配置的KeyGenerator的名称 全局key都会以他的策略去生成
cacheManager 自己配置的CacheManager 用来操作Cache对象的,很多对于缓存的配置也由他去管理

在标有@CacheConfig的类里面编写一个查询单个对象的方法并添加 @Cacheable注解

1 @Cacheable(key = "#id", unless = "#result == null") 
2 @PatchMapping("/course/{id}")
3 public Course courseInfo(@PathVariable Integer id) {
4     log.info("进来了 .. ");
5     return courseService.getCourseInfo(id);
6 }

执行完该方法后,执行结果将会被缓存到Redis:

SpringBoot2.x操作缓存的新姿势_第1张图片

 

 @Cacheable注解中参数详情见下表:

参数名 作用
cacheNames  被缓存的时候的命名空间
key 这里的key的优先级是最高的,可以覆盖掉全局配置的key,如果不配置的话使用的就是全局的key
keyGenerator  指定的缓存的key的生成器,默认没有
cacheManager  指定要使用哪个缓存管理器。默认是底层自动配置的管理器
condition 满足什么条件会进行缓存,里面可以写简单的表达式进行逻辑判断
unless 满足什么条件不进行缓存,里面可以写简单的表达式进行逻辑判断
sync 加入缓存的这个操作是否是同步的

Ⅱ、 修改

         编写一个修改的方法,参数传对象,返回值也改成这个对象

1 @PutMapping("/course")
2 public Course modifyCoruse(@RequestBody Course course) {
3     courseService.updateCourse(course);
4     return course;
5 }

        在方法上面添加 @CachePut(key = "#course.id") 注解,这个注解表示将方法的返回值更新到缓存中,注解中的参数和 @Cacheable 中的一样,这里就略过了。

Ⅲ、 删除

       编写删除方法,在方法上添加@CacheEvict 注解

1 @CacheEvict(key = "#id")
2 @DeleteMapping("/course/{id}")
3 public void removeCourse(@PathVariable Integer id) {
4     courseService.remove(id);
5 }

  @CacheEvict 的参数信息见下表:

参数名 描述
allEntries 是否删除该命名空间下面的全部缓存,默认是false
beforeInvocation 在执行删除方法前就执行清空缓存操作,默认是false,如果删除方法执行报错该注解则不执行

 

三、 基于代码的Cache的使用

          因为我们有配置的CacheManager,所以可以利用RedisCacheManager对象去手动操作cache,首先将CacheManager注入进来:

 1 @Resource 
 2 private CacheManager cacheManager;
 3 
 4 @PatchMapping("/course2/{id}")
 5 public Course course2(@PathVariable Integer id) {
 6     // 获取指定命名空间的cache
 7     Cache cache = cacheManager.getCache("course");
 8     // 通过key获取对应的value
 9     Cache.ValueWrapper wrapper = cache.get(2);
10     if (wrapper == null) {
11         // 查询数据库
12         Course course = courseService.getCourseInfo(id);
13         // 加入缓存
14         cache.put(course.getId(), course);
15         return course;
16     } else {
17         // 将缓存的结果返回
18         // 因为配置了enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
19         // 所以在进行强转的时候不会报错
20         return (Course) wrapper.get(); 
21     }
22 }

如果还看不明白,请去码云拉取源码 https://gitee.com/tianmaoliln/Spring-Boot-Cache.git

 

      你想成为什么样的人,就会成为什么样的人!

你可能感兴趣的:(SpringBoot2.x操作缓存的新姿势)