Spring Boot 揭祕與實戰(二) 資料快取篇 - 快速入門

樑桂釗發表於2017-01-05

為了提高效能,減少資料庫的壓力,使用快取是非常好的手段之一。本文,講解 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 揭祕與實戰(二) 資料快取篇 - 快速入門

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 Boot 揭祕與實戰(二) 資料快取篇 - 快速入門
  • 呼叫儲存介面,再呼叫查詢介面,檢視快取資訊是否變化?你得到的結論是什麼?
  • 呼叫刪除介面,再呼叫查詢介面,介面響應是否變慢了?你再看看控制檯日誌,你得到的結論是什麼?

擴充套件閱讀

如果想更深入理解 Spring 的 Cache 機制,這邊推薦兩篇不錯的文章。

原始碼

相關示例完整程式碼: springboot-action

(完)

更多精彩文章,盡在「服務端思維」微信公眾號!

Spring Boot 揭祕與實戰(二) 資料快取篇 - 快速入門

相關文章