為了提高效能,減少資料庫的壓力,使用快取是非常好的手段之一。本文,講解 Spring Boot 如何整合快取管理。
部落格地址:blog.720ui.com/
宣告式快取
Spring 定義 CacheManager 和 Cache 介面用來統一不同的快取技術。例如 JCache、 EhCache、 Hazelcast、 Guava、 Redis 等。在使用 Spring 整合 Cache 的時候,我們需要註冊實現的 CacheManager 的 Bean。
Spring Boot預設整合CacheManager
Spring Boot 為我們自動配置了多個 CacheManager 的實現。
Spring Boot 為我們自動配置了 JcacheCacheConfiguration、 EhCacheCacheConfiguration、HazelcastCacheConfiguration、GuavaCacheConfiguration、RedisCacheConfiguration、SimpleCacheConfiguration 等。
預設的 ConcurrenMapCacheManager
Spring 從 Spring3.1 開始基於 java.util.concurrent.ConcurrentHashMap 實現的快取管理器。所以, Spring Boot 預設使用 ConcurrentMapCacheManager 作為快取技術。
以下是我們不引入其他快取依賴情況下,控制檯列印的日誌資訊。
Bean 'cacheManager' of type [class org.springframework.cache.concurrent.ConcurrentMapCacheManager]複製程式碼
實戰演練
Maven 依賴
首先,我們先建立一個 POM 檔案。
<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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>
<groupId>com.lianggzone.demo</groupId>
<artifactId>springboot-action-cache</artifactId>
<version>0.1</version>
<packaging>jar</packaging>
<name>springboot-action-cache</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<useDefaultDelimiters>false</useDefaultDelimiters>
<escapeString>\</escapeString>
<delimiters>
<delimiter>${*}</delimiter>
</delimiters>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>複製程式碼
其中,最核心的是新增 spring-boot-starter-cache 依賴。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>複製程式碼
開啟快取支援
在 Spring Boot 中使用 @EnableCaching 開啟快取支援。
@Configuration
@EnableCaching
public class CacheConfiguration {}複製程式碼
服務層
建立一個服務類
@Service("concurrenmapcache.cacheService")
public class CacheService {
}複製程式碼
首先,我們先來講解下 @Cacheable 註解。@Cacheable 在方法執行前 Spring 先檢視快取中是否有資料,如果有資料,則直接返回快取資料;若沒有資料,呼叫方法並將方法返回值放進快取。有兩個重要的值, value,返回的內容將儲存在 value 定義的快取的名字物件中。key,如果不指定將使用預設的 KeyGenerator 生成。
我們在查詢方法上,新增 @Cacheable 註解,其中快取名稱為 concurrenmapcache。
@Cacheable(value = "concurrenmapcache")
public long getByCache() {
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Timestamp(System.currentTimeMillis()).getTime();
}複製程式碼
@CachePut 與 @Cacheable 類似,但是它無論什麼情況,都會將方法的返回值放到快取中, 主要用於資料新增和修改方法。
@CachePut(value = "concurrenmapcache")
public long save() {
long timestamp = new Timestamp(System.currentTimeMillis()).getTime();
System.out.println("進行快取:" + timestamp);
return timestamp;
}複製程式碼
@CacheEvict 將一條或多條資料從快取中刪除, 主要用於刪除方法,用來從快取中移除相應資料。
@CacheEvict(value = "concurrenmapcache")
public void delete() {
System.out.println("刪除快取");
}複製程式碼
控制層
為了展現效果,我們先定義一組簡單的 RESTful API 介面進行測試。
@RestController("concurrenmapcache.cacheController")
@RequestMapping(value = "/concurrenmapcache/cache")
public class CacheController {
@Autowired
private CacheService cacheService;
/**
* 查詢方法
*/
@RequestMapping(value = "", method = RequestMethod.GET)
public String getByCache() {
Long startTime = System.currentTimeMillis();
long timestamp = this.cacheService.getByCache();
Long endTime = System.currentTimeMillis();
System.out.println("耗時: " + (endTime - startTime));
return timestamp+"";
}
/**
* 儲存方法
*/
@RequestMapping(value = "", method = RequestMethod.POST)
public void save() {
this.cacheService.save();
}
/**
* 刪除方法
*/
@RequestMapping(value = "", method = RequestMethod.DELETE)
public void delete() {
this.cacheService.delete();
}
}複製程式碼
執行
@RestController
@EnableAutoConfiguration
@ComponentScan(basePackages = { "com.lianggzone.springboot" })
public class WebMain {
public static void main(String[] args) throws Exception {
SpringApplication.run(WebMain.class, args);
}
}複製程式碼
課後作業
我們分為幾個場景進行測試。
- 多次呼叫查詢介面,檢視快取資訊是否變化,控制檯日誌是否如下?你得到的結論是什麼?
- 呼叫儲存介面,再呼叫查詢介面,檢視快取資訊是否變化?你得到的結論是什麼?
- 呼叫刪除介面,再呼叫查詢介面,介面響應是否變慢了?你再看看控制檯日誌,你得到的結論是什麼?
擴充套件閱讀
如果想更深入理解 Spring 的 Cache 機制,這邊推薦兩篇不錯的文章。
原始碼
相關示例完整程式碼: springboot-action
(完)
更多精彩文章,盡在「服務端思維」微信公眾號!