SpringBoot集成cache緩存的實現(xiàn)
前言
日常開發(fā)中,緩存是解決數(shù)據(jù)庫壓力的一種方案,通常用于頻繁查詢的數(shù)據(jù),例如新聞中的熱點新聞,本文記錄springboot中使用cache緩存。
工程結(jié)構(gòu)

代碼編寫
pom引入依賴,引入cache緩存,數(shù)據(jù)庫使用mysql,ORM框架用jpa
<!--添加springdata-cache依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- 引入ehcache支持 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<!--添加springdata-jpa依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--添加MySQL驅(qū)動依賴 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
配置文件
server.port=10010 spring.application.name=springboot-cache spring.cache.type=ehcache spring.cache.ehcache.config=classpath:/ehcache.xml
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false">
<!-- 磁盤緩存位置 -->
<diskStore path="java.io.tmpdir"/>
<!-- maxEntriesLocalHeap:堆內(nèi)存中最大緩存對象數(shù),0沒有限制 -->
<!-- maxElementsInMemory: 在內(nèi)存中緩存的element的最大數(shù)目。-->
<!-- eternal:elements是否永久有效,如果為true,timeouts將被忽略,element將永不過期 -->
<!-- timeToIdleSeconds:發(fā)呆秒數(shù),發(fā)呆期間未訪問緩存立即過期,當(dāng)eternal為false時,這個屬性才有效,0為不限制 -->
<!-- timeToLiveSeconds:總存活秒數(shù),當(dāng)eternal為false時,這個屬性才有效,0為不限制 -->
<!-- overflowToDisk: 如果內(nèi)存中數(shù)據(jù)超過內(nèi)存限制,是否要緩存到磁盤上 -->
<!-- statistics:是否收集統(tǒng)計信息。如果需要監(jiān)控緩存使用情況,應(yīng)該打開這個選項。默認為關(guān)閉(統(tǒng)計會影響性能)。設(shè)置statistics="true"開啟統(tǒng)計 -->
<!--
默認緩存
無過期時間,但 600 秒內(nèi)無人訪問緩存立即過期
-->
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="600"
timeToLiveSeconds="0"
overflowToDisk="false">
</defaultCache>
<!--
xx業(yè)務(wù)緩存
在有效的 120 秒內(nèi),如果連續(xù) 60 秒未訪問緩存,則緩存失效。
就算有訪問,也只會存活 120 秒。
-->
<cache name="myCache"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="0"
overflowToDisk="false">
</cache>
</ehcache>
先寫一個套tb_user表的CRUD代碼

@RestController
@RequestMapping("/tbUser/")
public class TbUserController {
@Autowired
private TbUserService tbUserService;
//方便測試暫時改成GetMapping
@GetMapping("list")
// @PostMapping("list")
public List<TbUser> list(TbUser entityVo) {
return tbUserService.list(entityVo);
}
@GetMapping("get/{id}")
public TbUser get(@PathVariable("id")Integer id) {
return tbUserService.get(id);
}
//方便測試暫時改成GetMapping
@GetMapping("save")
// @PostMapping("save")
public TbUser save(TbUser entityVo) {
return tbUserService.save(entityVo);
}
@GetMapping("delete/{id}")
public Integer delete( @PathVariable("id") Integer id) {
return tbUserService.delete(id);
}
}
opjo實體類要實現(xiàn)序列化
@Entity
@Table(name = "tb_user")
@Data
public class TbUser implements Serializable {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Integer id;//表id
private String username;//用戶名
private String password;//密碼
private Date created;//創(chuàng)建時間
private Integer descriptionId;//關(guān)聯(lián)詳情id
}
serviceImpl中,使用注解來開啟緩存
@Service
@Transactional
@CacheConfig(cacheNames = {"myCache"})
public class TbUserServiceImpl implements TbUserService{
@PersistenceContext
private EntityManager em;
@Autowired
private TbUserRepository tbUserRepository;
//@Cacheable緩存數(shù)據(jù):key為userList,value為返回值List<TbUser>
@Cacheable(key = "'userList'")
@Override
public List<TbUser> list(TbUser entityVo) {
System.out.println("獲取list用戶列表緩存數(shù)據(jù),"+new Date());
return tbUserRepository.findAll(Example.of(entityVo));
}
//@Cacheable緩存數(shù)據(jù):key為參數(shù)id,value為返回值TbUser
@Cacheable(key = "#id")
@Override
public TbUser get(Integer id) {
System.out.println("獲取數(shù)據(jù)緩存,key:"+id);
Optional<TbUser> optionalE = tbUserRepository.findById(id);
if (!optionalE.isPresent()) {
throw new RuntimeException("ID不存在!");
}
return optionalE.get();
}
//@CachePut緩存新增的或更新的數(shù)據(jù)到緩存,其中緩存的名稱為people,數(shù)據(jù)的key是person的id
@CachePut(key = "#entityVo.id")
// @CacheEvict從緩存中刪除key為參數(shù)userList的數(shù)據(jù)
@CacheEvict(key = "'userList'")
@Override
public TbUser save(TbUser entityVo) {
System.out.println("新增/更新緩存,key:"+entityVo.getId());
//entityVo傳啥存啥,會全部更新
return tbUserRepository.save(entityVo);
}
//清空所有緩存
@CacheEvict(allEntries=true)
@Override
public Integer delete(Integer id) {
System.out.println("清空所有緩存");
tbUserRepository.deleteById(id);
return id;
}
}
效果演示
http://localhost:10010/tbUser/save?id=2&username=李四
調(diào)用save方法,key為2,value為當(dāng)前tbUser對象的數(shù)據(jù)被緩存下來


http://localhost:10010/tbUser/get/2
當(dāng)我們調(diào)用get方法時,直接獲取緩存數(shù)據(jù),控制臺啥也不打印,連serviceImpl的get方法都不進去(可以打斷點調(diào)試)


http://localhost:10010/tbUser/save?id=2&username=王五
當(dāng)我們再次調(diào)用save方法更新username時,緩存數(shù)據(jù)也被更新


http://localhost:10010/tbUser/get/2
再次調(diào)用get接口,直接返回緩存數(shù)據(jù),后臺也是方法都不進去,啥也不打印


http://localhost:10010/tbUser/delete/2
調(diào)用delete接口,刪除數(shù)據(jù),同時刪除緩存


再次調(diào)用get接口,發(fā)現(xiàn)緩存數(shù)據(jù)被清除,查詢數(shù)據(jù)庫

http://localhost:10010/tbUser/list
首次調(diào)用list接口,key為userList的,value為用戶集合數(shù)據(jù)被緩存下來,再次調(diào)用直接返回緩存數(shù)據(jù)


當(dāng)調(diào)用save接口,數(shù)據(jù)更新,刪除key為userList的緩存,再次調(diào)用list時,重新查庫并設(shè)置緩存

我們配置了緩存發(fā)呆時間,當(dāng)120秒內(nèi)未使用該緩存,立即過期,一直用就會一直存在
我們先同時訪問兩個接口list、get,list接口2分鐘后再次訪問,get接口不能超過2分鐘是不是訪問一下,結(jié)果如預(yù)期

PS:原先使用了這個jar包,有報錯
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.8.1</version>
</dependency>
后面改成用上面“代碼編寫”里pom中引的jnet.sf.ehcache下面的ar
后記
緩存除了能緩解數(shù)據(jù)庫壓力,還能做用戶登錄狀態(tài)控制,例如:用戶登錄成功后cookie中保存頒發(fā)的token令牌設(shè)置永不過期,緩存存活時間也設(shè)置永不過期,發(fā)呆時間設(shè)置1天,這樣只有用戶在1天內(nèi)有訪問緩存接口,那他就可以一直保留登錄狀態(tài),直至有其他業(yè)務(wù)將token或者緩存清掉。
springboot使用cache緩存暫時先記錄到這,后續(xù)有空再進行補充。
代碼開源
代碼已經(jīng)開源、托管到我的GitHub、碼云:
GitHub:https://github.com/huanzi-qch/springBoot
碼云:https://gitee.com/huanzi-qch/springBoot
到此這篇關(guān)于SpringBoot集成cache緩存的實現(xiàn)的文章就介紹到這了,更多相關(guān)SpringBoot cache緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解如何讓Spring MVC顯示自定義的404 Not Found頁面
這篇文章主要介紹了詳解如何讓Spring MVC顯示自定義的404 Not Found頁面,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-10-10
MybatisPlus如何自定義TypeHandler映射JSON類型為List
這篇文章主要介紹了MybatisPlus如何自定義TypeHandler映射JSON類型為List,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01
如何從eureka獲取服務(wù)的ip和端口號進行Http的調(diào)用
這篇文章主要介紹了如何從eureka獲取服務(wù)的ip和端口號進行Http的調(diào)用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
淺析java修飾符訪問權(quán)限(動力節(jié)點Java學(xué)院整理)
Java有四種訪問權(quán)限,其中三種有訪問權(quán)限修飾符,分別為private,public和protected,還有一種不帶任何修飾符,下面通過本文給大家簡單介紹下java修飾符訪問權(quán)限相關(guān)知識,感興趣的朋友一起學(xué)習(xí)吧2017-04-04
淺談Java的Synchronized鎖原理和優(yōu)化
這篇文章主要介紹了Java的Synchronized鎖原理和優(yōu)化,synchronized的作用是保證在同一時刻, 被修飾的代碼塊或方法只會有一個線程執(zhí)行,以達到保證并發(fā)安全的效果,需要的朋友可以參考下2023-05-05

