文章目錄
-
- 1. 配置
-
- 1.1 基本配置
- 1.2 ehcache
- 1.3 diskStore
- 1.4 defaultCache
- 1.5 cache配置項
- 1.6 通過程式設計式配置
- 2. Spring與Ehcache
-
- 2.1 @Cacheable
- 2.2 @CachePut
- 2.3 @CacheEvict
- 3. 執行個體與測試
-
- 3.1 maven依賴
- 3.2 spring 配置
- 3.3 Ehcache配置
- 3.4 啟動類
- 3.5 實體類
- 3.6 Repository
- 3.7 緩存邏輯
- 3.8 測試類
- 4. 文檔資料
1. 配置
1.1 基本配置
下面基本算是使用Ehcache的xml最簡配置了。
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="mycache-manager" updateCheck="false">
<!-- 磁盤緩存位置 -->
<diskStore path="java.io.tmpdir/ehcache"/>
<!-- 預設緩存 -->
<defaultCache
maxEntriesLocalHeap="1000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="false">
</defaultCache>
<!-- 使用者緩存政策 -->
<cache name="userCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
</ehcache>
1.2 ehcache
每個ehcache對應一個CacheManager,ehcache的name用來配置CacheManager的名稱。
可以通過下面的方式擷取:
1.3 diskStore
diskStore用來配置緩存資料儲存的磁盤位置,常用的三個:
- user.home:使用者主目錄
- user.dir:使用者目前工作目錄
- java.io.tmpdir:預設臨時檔案路徑
當然也可以使用絕對路徑
1.4 defaultCache
預設緩存政策,當Ehcache沒有找到緩存政策的時候,就會使用這個緩存政策,隻能定義一個預設政策。
1.5 cache配置項
緩存政策,設定緩存逾時時間,最大緩存數目等。
配置項 | 說明 |
---|---|
name | 緩存的名稱,可以通過指定名稱擷取指定的某個Cache對象 |
eternal | true,永不過期,逾時設定将被忽略,一些靜态的配置資料可以設定為true |
statistics | 是否收集統計資訊,如果需要監控緩存使用情況,應該設定為true,預設false,統計對性能有影響 |
clearOnFlush | 記憶體數量最大時是否清除 |
overflowToDisk | 記憶體不足時,是用磁盤進行緩存 |
diskPersistent | 是否啟用磁盤持久化的機制,JVM重新開機時可以加載之前緩存,預設值是false |
timeToIdleSeconds | 對象允許閑置時間,機關秒,逾時過期,0表示可以一直空閑 |
timeToLiveSeconds | 緩存資料最多存活時間,0表示不過期,timeToLiveSeconds不等于0時應該大于timeToIdleSeconds |
maxElementsOnDisk | 磁盤最大緩存多少cache數量 |
maxElementsInMemory | 記憶體中允許存儲的最大的元素個數,0代表無限個 |
maxEntriesLocalDisk | 當記憶體中對象數量達到maxElementsInMemory時,Ehcache将會對象寫到磁盤中 |
maxEntriesLocalHeap | 堆記憶體中最大緩存對象數,0表示沒有限制 |
diskSpoolBufferSizeMB | 設定磁盤緩存的緩存區大小,預設是30MB,每個Cache都應該有自己的一個緩沖區 |
memoryStoreEvictionPolicy | 緩存達到maxElementsInMemory限制時,記憶體緩存過期政策算法,LRU(最近最少使用,預設)、FIFO(先進先出)、LFU(最少通路次數) |
diskExpiryThreadIntervalSeconds | 檢查磁盤緩存資料過期線程運作時間間隔,預設是120秒 |
1.6 通過程式設計式配置
@Test
public void createCache(){
CacheManager cacheManager = CacheManager.create();
Cache cache = new Cache("cacheName", 1000, true, false, 120, 120);
CacheConfiguration config = cache.getCacheConfiguration();
config.setClearOnFlush(true);
config.setMaxEntriesLocalHeap(100);
cacheManager.addCache(cache);
}
2. Spring與Ehcache
Spring對緩存的支援,是通過代理實作的,直接通過注解标就可以實作緩存,基本不需要處理太多和緩存相關的邏輯。
Spring的幾個緩存相關的注解參數都支援SpEL表達式,下面是幾個SpEL常用表達:
屬性 | 位置 | 說明 | 示例 |
---|---|---|---|
args | root | 目前方法參數數組 | #root.args[0] |
method | root | 目前方法 | #root.method.name |
target | root | 目前被調用的對象 | #root.target |
caches | root | 目前被調用的方法使用的Cache | #root.caches[0].name |
methodName | root | 目前方法名 | #root.methodName |
targetClass | root | 目前被調用的對象的class | #root.targetClass |
argument | context | 目前被調用的參數,saveUser(User user) | #user.id |
result | context | 目前被調用的傳回值 | #result |
2.1 @Cacheable
用@Cacheable注解的方法表示會緩存改方法的傳回值。
當第一次調用這個方法時,方法的傳回值會被緩存下來,在緩存的有效時間内,以後通路這個方法都直接傳回緩存結果,不再執行方法中的代碼段。
@Cacheable參數:
- value:緩存政策名稱用于查找緩存位置,不能為空,Ehcache就是xml配置的cache的name,說明緩存資料放到哪個Cache中
- key:指定緩存使用的key,預設為空,既表示使用方法的參數類型及參數值作為key,支援SpEL
- condition:觸發條件,隻有滿足條件的情況才會加入緩存,預設為空,既表示全部都加入緩存,支援SpEL
2.2 @CachePut
@CachePut和@Cacheable基本一樣,但是它每次都會執行方法。一般用在更新方法上,這樣可以同時更新緩存和資料庫。
2.3 @CacheEvict
@CacheEvict用來删除緩存資料,它有參數:
- value:緩存政策名稱用于查找緩存位置,不能為空
- key:緩存的key,預設為空
- condition:觸發條件,隻有滿足條件的情況才會清除緩存,預設為空
- allEntries:是否清除全部緩存,預設為false,true表示清除value指定政策中的全部緩存
3. 執行個體與測試
3.1 maven依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--Spring Boot應用程式提供緩存支援-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--Ehcache緩存實作-->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<!--JSR-107緩存規範-->
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
依賴中忽略了spring-boot-starter-parent,選擇自己喜歡的版本加入:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
</parent>
3.2 spring 配置
logging.config=classpath:logback.xml
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/data?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.username=tim
spring.datasource.password=123456
spring.jpa.database=MySQL
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.cache.jcache.config=classpath:ehcache.xml
3.3 Ehcache配置
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="mycache-manager" updateCheck="false">
<!-- 緩存資料磁盤位置 -->
<diskStore path="java.io.tmpdir"/>
<!-- 預設緩存 -->
<defaultCache
maxEntriesLocalHeap="1000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="false">
</defaultCache>
<!-- 使用者緩存政策 -->
<cache name="userCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="60"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="true">
</cache>
</ehcache>
将diskPersistent設定為true,友善執行不同Test的時候,還保留之前的緩存。
這裡使用的是Ehcache的2.x版本,3.x版本做了很多的變化,實作了JSR-107,如果可以盡量選擇3.x的版本。
Ehcache配置類:
@Configuration
@EnableCaching
public class EhcacheConfiguration {
@Bean(name = "ehCacheCacheManager")
public EhCacheCacheManager ehCacheCacheManager(EhCacheManagerFactoryBean bean){
return new EhCacheCacheManager(bean.getObject());
}
@Bean
public EhCacheManagerFactoryBean ehCacheManagerFactoryBean(){
EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean();
ClassPathResource classPathResource = new ClassPathResource("ehcache.xml");
cacheManagerFactoryBean.setConfigLocation (classPathResource);
cacheManagerFactoryBean.setShared(true);
return cacheManagerFactoryBean;
}
}
使用@EnableCaching注解開啟Spring緩存。
3.4 啟動類
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
@EnableJpaRepositories(basePackages = {"vip.mycollege.jpa.mysql.repository"})
public class Start {
public static void main(String[] args) {
SpringApplication.run(Start.class, args);
}
}
3.5 實體類
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
@Entity
@Table(name = "user")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer id;
private Integer age;
@Column(length = 20)
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
實體類要實作Serializable,Ehcache持久化對象到磁盤需要。
3.6 Repository
import org.springframework.data.repository.CrudRepository;
import vip.mycollege.jpa.mysql.entity.User;
public interface UserRepository extends CrudRepository<User,Integer> {
}
3.7 緩存邏輯
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import vip.mycollege.jpa.mysql.entity.User;
import vip.mycollege.jpa.mysql.repository.UserRepository;
import javax.annotation.Resource;
@Service
public class EhcacheService {
@Resource
private UserRepository userRepository;
@Cacheable(value="userCache", key="'user:' + #id")
public User findUserById(Integer id) {
System.out.println("execute findUserById");
return userRepository.findById(id).get();
}
@Cacheable(value="userCache", condition="#id < 3")
public User findCacheConditionUserById(Integer id) {
System.out.println("execute findCacheConditionUserById");
return userRepository.findById(id).get();
}
@CacheEvict(value="userCache",key="'user:' + #user.id")
public void deleteUser(User user) {
System.out.println("execute deleteUser");
userRepository.deleteById(user.getId());
}
@CacheEvict(value="userCache", allEntries=true)
public void deleteAllUserCache() {
System.out.println("execute deleteAllUserCache");
System.out.println("delete all cache");
}
@CachePut(value = "userCache",key = "'user:'+#user.id")
public User updateUser(User user) {
System.out.println("execute updateUser");
user.setAge(100);
userRepository.save(user);
return user;
}
}
可以自己生成一些資料,然後用下面的測試類來測試不同緩存的效果。
3.8 測試類
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import vip.mycollege.jpa.mysql.entity.User;
import javax.annotation.Resource;
@RunWith(SpringRunner.class)
@SpringBootTest
public class EhcacheServiceTest {
@Resource
private EhcacheService ehcacheService;
@Test
public void findUserById() {
User user = ehcacheService.findUserById(1);
System.out.println(user);
}
@Test
public void findCacheConditionUserById() {
User user = ehcacheService.findCacheConditionUserById(5);
System.out.println(user);
}
@Test
public void deleteUser() {
User user = new User();
user.setId(1);
ehcacheService.deleteUser(user);
}
@Test
public void deleteAllUserCache() {
ehcacheService.deleteAllUserCache();
}
@Test
public void updateUser() {
User user = new User();
user.setId(1);
ehcacheService.updateUser(user);
}
}
4. 文檔資料
Ehcache2.9文檔
Ehcache3.8文檔
Ehcache快速開始
Ehcache示例
SpringBoot緩存文檔