本文講解Spring Boot與EhCache的整合。
1 EhCache簡介
EhCache 是一個純Java的進程內緩存框架,具有快速、精干等特點,是Hibernate中默認CacheProvider。Ehcache是一種廣泛使用的開源Java分布式緩存。主要面向通用緩存,Java EE和輕量級容器。它具有內存和磁盤存儲,緩存加載器,緩存擴展,緩存異常處理程序,一個gzip緩存servlet過濾器,支持REST和SOAP api等特點。
2 Spring Boot整合EhCache步驟
2.1 創建項目,導入依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yiidian</groupId>
<artifactId>ch03_10_springboot_ehcache</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 導入springboot父工程. 注意:任何的SpringBoot工程都必須有的!!! -->
<!-- 父工程的作用:鎖定起步的依賴的版本號,並沒有真正到依賴 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.11.RELEASE</version>
</parent>
<dependencies>
<!--web起步依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--springboot 集成 junit 起步依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.6.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- 緩存坐標 -->
<!-- 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.1.11.RELEASE</version>
</dependency>
<!-- Ehcache支持 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.6</version>
</dependency>
</dependencies>
</project>
2.2 配置ehcache.xml
在resources目錄下建立ehcache.xml
,內容如下:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="java.io.tmpdir"/>
<!-- defaultCache: 默認配置 -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</defaultCache>
<!-- 緩存名稱為customer的配置 -->
<cache name="customer"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</cache>
</ehcache>
參數說明:
- name 緩存名稱
- maxElementsInMemory 緩存最大個數
- eternal 對象是否永久有效,一但設置了,timeout將不起作用
- timeToIdleSeconds 設置對象在失效前的允許閑置時間(單位:秒)。僅當eternal=false對象不是永久有效時使用,可選屬性,默認值是0,也就是可閑置時間無窮大
- timeToLiveSeconds 設置對象在失效前允許存活時間(單位:秒)。最大時間介於創建時間和失效時間之間。僅當eternal=false對象不是永久有效時使用,默認是0.,也就是對象存活時間無窮大
- overflowToDisk 當內存中對象數量達到maxElementsInMemory時,Ehcache將會對象寫到磁盤中
- diskSpoolBufferSizeMB 這個參數設置DiskStore(磁盤緩存)的緩存區大小。默認是30MB。每個Cache都應該有自己的一個緩沖區
- maxElementsOnDisk 硬盤最大緩存個數
- diskPersistent 是否緩存虛擬機重啟期數據
- diskExpiryThreadIntervalSeconds 磁盤失效線程運行時間間隔,默認是120秒。
- memoryStoreEvictionPolicy 當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理內存。默認策略是LRU(最近最少使用)。你可以設置為FIFO(先進先出)或是LFU(較少使用)
- clearOnFlush 內存數量最大時是否清除
2.3 編寫application.yml
#配置EhCache的配置
spring:
cache:
ehcache:
config: ehcache.xml # 讀取ehcache.xml配置
2.4 編寫引導類
package com.yiidian;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
/**
* Spring Boot引導類
* 一點教程網 - www.yiidian.com
*/
@SpringBootApplication
@EnableCaching // 開啟緩存
public class MyBootApplication {
public static void main(String[] args) {
SpringApplication.run(MyBootApplication.class,args);
}
}
引導類中需要添加@EnableCaching注解,開啟緩存功能
2.5 編寫Service類
package com.yiidian.service;
import com.yiidian.domain.Customer;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
/**
* 業務層
*一點教程網 - www.yiidian.com
*/
@Service
public class CustomerService {
@Cacheable(value = "customer",key = "#id")
public Customer findById(Integer id){
System.out.println("執行了UserService獲取User");
Customer customer = new Customer();
customer.setId(1);
customer.setName("小明");
customer.setGender("男");
customer.setTelephone("13244445555");
return customer;
}
}
@Cacheable的屬性:
- value:對應ehcache.xml的緩存配置名稱(name屬性值)
- key:給緩存值起個key,便於Spring內部檢索不同的緩存數據。#id這個語法代表把方法形參作為key。
2.6 編寫測試類
package com.yiidian.test;
import com.yiidian.MyBootApplication;
import com.yiidian.service.CustomerService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* SpringBoot整合EhCache
* 一點教程網 - www.yiidian.com
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = MyBootApplication.class)
public class EhCacheDemo {
@Autowired
private CustomerService customerService;
@Test
public void test1(){
//查詢第一次
System.out.println(customerService.findById(1));
//查詢第二次
System.out.println(customerService.findById(1));
}
}
2.7 運行測試
從結果可以看出,第一次調用Service的時候,到Service內部獲取數據。但是第二次調用Service時已經不需要從Service獲取數據,證明第一次查詢的時候已經把Customer對象緩存到EhCache中。
3 EhCache常用注解
- @Cacheable: 主要針對方法配置,能夠根據方法的請求參數對其進行緩存
- @CacheConfig: 統一配置本類的緩存注解的屬性
- @CachePut:保證方法被調用,又希望結果被緩存。與@Cacheable區別在於是否每次都調用方法,常用於更新
- @CacheEvict :清空緩存
@Cacheable/@CachePut/@CacheEvict 主要的參數:
- value:緩存的名稱,在 spring 配置文件中定義,必須指定至少一個
例如:
@Cacheable(value=”mycache”) 或者
@Cacheable(value={”cache1”,”cache2”} - key:緩存的 key,可以為空,如果指定要按照 SpEL 表達式編寫,
如果不指定,則缺省按照方法的所有參數進行組合
例如:
@Cacheable(value=”testcache”,key=”#id”) - condition:緩存的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,
只有為 true 才進行緩存/清除緩存
例如:@Cacheable(value=”testcache”,condition=”#userName.length()>2”) - unless 否定緩存。當條件結果為TRUE時,就不會緩存。
@Cacheable(value=”testcache”,unless=”#userName.length()>2”) - allEntries
(@CacheEvict ): 是否清空所有緩存內容,缺省為 false,如果指定為 true,
則方法調用后將立即清空所有緩存
例如:
@CachEvict(value=”testcache”,allEntries=true) - beforeInvocation
(@CacheEvict): 是否在方法執行前就清空,缺省為 false,如果指定為 true,
則在方法還沒有執行的時候就清空緩存,缺省情況下,如果方法
執行拋出異常,則不會清空緩存
例如:
@CachEvict(value=”testcache”,beforeInvocation=true)
3.1 @Cacheable
@Cacheable注解會先查詢是否已經有緩存,有會使用緩存,沒有則會執行方法並緩存。
@Cacheable(value = "customer" ,key = "targetClass + methodName +#p0")
public List<Customer> queryAll(Customer cust) {
return customerDao.findAllByUid(cust);
}
3.2 @CacheConfig
當我們需要緩存的地方越來越多,你可以使用@CacheConfig(cacheNames = {"myCache"})注解來統一指定value的值,這時可省略value,如果你在你的方法依舊寫上了value,那么依然以方法的value值為准。
使用方法如下:
@CacheConfig(cacheNames = {"myCache"})
public class UserServiceImpl implements UserService {
@Override
@Cacheable(key = "targetClass + methodName +#p0")//此處沒寫value
public List<BotRelation> findUsers(int num) {
return userDao.findUsers(num);
}
.....
}
3.3 @CachePut
@CachePut注解的作用 主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存,和 @Cacheable 不同的是,它每次都會觸發真實方法的調用 。簡單來說就是用戶更新緩存數據。但需要注意的是該注解的value 和 key 必須與要更新的緩存相同,也就是與@Cacheable 相同。示例:
@CachePut(value = "customer", key = "targetClass + #p0")
public Customer updata(Customer cust) {
Customer customer = customerDao.findAllById(cust.getId());
customer.updata(cust);
return customer ;
}
@Cacheable(value = "customer", key = "targetClass +#p0")//清空緩存
public Customer save(Customer cust) {
customerDao.save(cust);
return cust;
}
3.4 @CacheEvict
@CachEvict 的作用 主要針對方法配置,能夠根據一定的條件對緩存進行清空 。
@Cacheable(value = "customer",key = "#p0.id")
public Customer save(Customer cust) {
customerDao.save(cust);
return job;
}
//清除一條緩存,key為要清空的數據
@CacheEvict(value="customer",key="#id")
public void delect(int id) {
customerDao.deleteAllById(id);
}
//方法調用后清空所有緩存
@CacheEvict(value="customerCache",allEntries=true)
public void delectAll() {
customerDao.deleteAll();
}
//方法調用前清空所有緩存
@CacheEvict(value="customerCache",beforeInvocation=true)
public void delectAll() {
customerDao.deleteAll();
}
歡迎關注我的公眾號::一點教程。獲得獨家整理的學習資源和日常干貨推送。
如果您對我的系列教程感興趣,也可以關注我的網站:yiidian.com