文章目錄
為了提高性能,減少數據庫的壓力,使用緩存是非常好的手段之一。本文,講解 Spring Boot 如何集成緩存管理。
聲明式緩存
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
(完)
