Sring Cache的用法
概念
spring提供的缓存框架,spring cache通过一系列注解就可以操作缓存数据
导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>2.7.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.7.3</version>
</dependency>
工具
查看导入依赖的网站:https://mvnrepository.com/
常用注解
注意
在启动类里面添加@EnableCaching注解
准备
pom.xml
里边要有:缓存框架springcache+缓存中间件redis+mysql数据库驱动+mybatis操作+druid数据源+knife4j接口文档+test单元测试
application.yml
里边要有:Tomcat端口号+druid数据源+redis数据源+日志
@CachePut注解原理
@CachePut(cacheNames = "userCache", key = "abc")//如果使用spring cache缓存数据,key的生成:userCache::abc
Public User save(@RequestBody User user){
userMapper.insert(user);
return user;
}
这样写保存每一个用户时都是abc,key都是固定的一个值。(后边保存的缓存数据就会把前边的缓存数据覆盖掉,因为算出来的key都是相同的)
希望每一个用户保存在数据库的同时,对应自己的一个缓存数据。key需要区分开。
所以要动态计算key,保证每次插入一个用户的同时,计算出来的key都是动态的(和当前用户的唯一标识有关系)因为数据库表中的数据,它的主键值都是不同的,如果能拿到当前用户的id就能解决问题:
key=“**springEL**” key = "#user.id"(能动态的取到用户的id)
//cacheput是把返回值放进缓存,返回的user已经有id了通过spEL取出来作key
@Cacheable注解原理
spring cache底层基于代理技术,加入这个注解之后,spring cache就为当前controller创建一个代理对象,在请求这个方法之前,先进入代理对象,在代理对象里边查询redis。如果在redis缓存中查询到了数据,就不用调用getById的方法。如果没查询到,则通过反射调用该方法,方法里边要查询数据库并把数据返回,再把返回结果放入redis中缓存起来,等下一次查询该数据时,缓存中就有该数据了。
@CacheEvict注解原理
在代理对象中,动态地把key计算出来,然后通过代理对象来操作redis,最终把缓存数据给删除。
代码
@PostMapping
@CachePut(cacheNames = "userCache", key = "#user.id")//如果使用spring cache缓存数据,key的生成:userCache::1(双冒号表示2级目录,第一个冒号下面是空的目录)
//@CachePut(cacheNames = "userCache", key = "#result.id")//对象导航
//@CachePut(cacheNames = "userCache", key = "#p0.id")//取到第一个参数user
//@CachePut(cacheNames = "userCache", key = "#a0.id")
//@CachePut(cacheNames = "userCache", key = "#root.args[0].id")
Public User save(@RequestBody User user){
userMapper.insert(user);
return user;
}
@GetMapping
@Cacheable(cacheNames = "userCache", key = "#id")//该注解是在方法执行前生效,先查询redis是否有该数据,若有则不能获取到方法的结果。key的生成:userCache::2
public User getById(Long id){
User user = userMapper.getById(id);
return user;
}
@DeleteMapping
@CacheEvict(cacheNames = "userCache", key = "#id")//一次删除一条数据。key的生成:userCache::2
public void deleteById(Long id){
userMapper.deleteById(id);
}
@DeleteMapping("/delAll")
@CacheEvict(cacheNames = "userCache", allEntries = true)//一次删除多条数据key的生成:userCache::2
public void deleteAll(){
userMapper.deleteAll();
}
来自上海