一,前言
本篇會從兩個緩存講起,分別是JSR-107緩存,Spring抽象緩存;
二,什麼是JSR-107緩存
JSR是java Specification Requests的縮寫,意思是Java 規範提案(2012年10月26日發佈),JCache Api的首個早期提案,此次提案主要有哪些規範呢?
- 定義了一種對java對象臨時在內存中進行緩存的方法,一種對java對象臨時在內存中進行緩存的方法,一種對java對象臨時在內存中進行緩存的方法,重要事情說三遍。
- 其中包括對象的創建,共享訪問,失效,JVM一致性等,
JCache定義了Java標準的api。JCache主要定義了5個接口來規範緩存的生命週期
- CachingProvider 創建,配置,獲取,管理CacheManager
- CacheManager 創建,配置,獲取,管理Cache組件
- Cache 類似於Map的數據結構,用來保存需要緩存的Entry
- Entry 以K,V 鍵值對的形式來保存緩存數據
- Expiry 過期機制,用來設置當前Entry是否過期
注:Cache緩存組件通過name唯一標識,且與CacheManager是一對一的關係
由於在實際的使用場景中,Spring抽象緩存用的多,這裏就對JSR-107簡單介紹,接下來中的看Spring抽象緩存
Spring抽象緩存
爲了簡化緩存開發
spring從3.1開始定義了org.springframework.cache.Cache和
org.springframework.cache.CacheManager接口來統一不同的緩存技術;
並支持JCache(JSR-107)註解來簡化我們的開發
解析:
CacheManage:
緩存管理器,管理各種緩存組件
Cache:
緩存接口,定義緩存操作,實現的有RedisCache,EhCacheCache,ConcurrentMapCache等
Spring常用緩存註解:
- @Cacheable 針對方法的註解,默認根據方法的請求參數對該返回結果進行緩存
- @CacheEvict 清空緩存
- @CachePut 更新緩存,即使緩存中存在該請求結果,仍然會執行方法,並將緩存結果替換
- @EnableCaching 開啓緩存,用在啓動類上,開啓緩存
以上對緩存的概念和常用註解都做了介紹,接下來就來實際演示一遍!
- 搭建數據庫環境
- 創建一個學生表student ,字段id,sname,age,gender並錄入一些數據
- 創建對應的JavaBean
- 整合Mybatis,操作數據庫
1配置數據源信息&引入pom依賴
#數據源
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://192.168.43.201/chen?serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
//爲了後期便於觀察,打印指定路徑下的日誌
logging.level.com.best.demobeststartertest.Cache.mapper=debug
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
2編寫對應的Mapper接口
並使用@Mapper註解該類
@Mapper //在Mapper中實現查詢方法
public interface StudentMapper {
@Select("SELECT * from student where id=#{id}")
public Student getStudentById(Integer id);
@Delete("Delete from student where id=#{id}")
public boolean delStudentById(Integer id);
@Insert("Insert into student values(#{id},#{sname},#{age},#{gender})")
public boolean insetStu(Student student);
}
3編寫對應的Service處理業務邏輯
@Service //業務邏輯處理層
public class StudentService {
@Autowired
StudentMapper studentMapper;
//獲取查詢結果
public Student getSt(Integer id){
System.out.println("查詢id爲"+id+"的學生");
Student student=studentMapper.getStudentById(id);
return student;
}
//插入數據
public boolean InsertSt(Student student){
boolean xx=studentMapper.insetStu(student);
return xx;
}
}
4編寫Control控制檯
@RestController
public class StudentControl {
@Autowired
StudentService studentService;
//對該方法使用緩存
/*
解析一下此註解,主要有如下重要屬性
1 cacheNames:定義該緩存組件的名字。同時也是該組件的唯一標識,(緩存管理器就是通過緩存組件名稱來進行管理)
2 key 該緩存的key值,默認取值該方法的請求參數,例 #id
3 keyGenerator key的生成策略,與key的作用相同,二者取其一
4 condition 緩存的條件,滿足該條件,才進行緩存
5 unless 不緩存條件,滿足該條件,不進行緩存,通常會通過#result==null,當方法返回值爲空時,不進行緩存
6 CacheManager 指定緩存管理器,即爲當前的緩存組件指定唯一對應的管理器
7 cacheResolver 緩存解析器,同樣是對緩存進行管理,與CacheManager二者選其一
8 sync 是否異步
如下,我們給該緩存組件取名爲xxxtent
*/
@Cacheable(cacheNames="xxxtent")
@RequestMapping("/Cache/getStudent/{id}") //將路徑變量中取出Id佔位符
public Student getStudent(@PathVariable("id") Integer id){
Student student=studentService.getSt(id);
return student;
}
@RequestMapping("/Cache/InsertStuent")
public boolean InsertStudent(Student student){
boolean xx=studentService.InsertSt(student);
return xx;
}
}
5啓動測試類,並查看控制檯數據
第一次請求時,由於緩存中沒有對應的數據,故執行方法
2020-02-02 17:33:50.104 DEBUG 1676 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : GET "/Cache/getStudent/8", parameters={}
2020-02-02 17:33:50.177 DEBUG 1676 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.best.demobeststartertest.Cache.Controller.StudentControl#getStudent(Integer)
查詢id爲8的學生
第二次發送同樣請求,該緩存中存在對應數據,直接返回,不執行方法,故控制檯未產生新數據