1. 程式人生 > >第七篇:Spring Boot整合Spring Cache

第七篇:Spring Boot整合Spring Cache

為了提高效能,減少資料庫的壓力,使用快取是非常好的手段之一。因此本文講解 Spring Boot 如何整合快取管理。

宣告式快取

Spring 定義 CacheManager 和 Cache 介面用來統一不同的快取技術。例如 JCache、 EhCache、 Hazelcast、 Guava、 Redis 等。在使用 Spring 整合 Cache 的時候,我們需要註冊實現CacheManager 的 Bean。

幾個重要概念&快取註解

在這裡插入圖片描述

@Cacheable/@CachePut/@CacheEvict 主要的引數

在這裡插入圖片描述

SpEL上下文資料

在這裡插入圖片描述

注意:

  1. 當我們要使用root物件的屬性作為key時我們也可以將“#root”省略,因為Spring預設使用的就是root物件的屬性。 如
@Cacheable(key = "targetClass + methodName +#p0")
  1. 使用方法引數時我們可以直接使用“#引數名”或者“#p引數index”。 如:
@Cacheable(value="users", key="#id")
@Cacheable(value="users", key="#p0")

SpEL提供了多種運算子

在這裡插入圖片描述

Spring Boot預設整合CacheManager

Spring Boot 為我們自動配置了多個 CacheManager 的實現。
在這裡插入圖片描述
Spring Boot 為我們自動配置了 JcacheCacheConfiguration、 EhCacheCacheConfiguration、HazelcastCacheConfiguration、GuavaCacheConfiguration、RedisCacheConfiguration、SimpleCacheConfiguration 等。

預設使用 ConcurrenMapCacheManager

在我們不使用其他第三方快取依賴的時候,springboot自動採用ConcurrenMapCacheManager作為快取管理器。

環境依賴

Ehcache是一種廣泛使用的開源Java分散式快取。主要面向通用快取,Java EE和輕量級容器。它具有記憶體和磁碟儲存,快取載入器,快取擴充套件,快取異常處理程式,一個gzip快取servlet過濾器,支援REST和SOAP api等特點。本文使用Ehcache,在pom檔案引入spring-boot-starter-cache和ehcache環境依賴:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

yml配置

需要說明的是config: classpath:/ehcache.xml可以不用寫,因為預設就是這個路徑。但ehcache.xml必須有。

spring:  
  cache:
    type: ehcache
    ehcache:
      config: classpath:/ehcache.xml

ehcache.xml

<ehcache>

    <!--
        磁碟儲存:將快取中暫時不使用的物件,轉移到硬碟,類似於Windows系統的虛擬記憶體
        path:指定在硬碟上儲存物件的路徑
        path可以配置的目錄有:
            user.home(使用者的家目錄)
            user.dir(使用者當前的工作目錄)
            java.io.tmpdir(預設的臨時目錄)
            ehcache.disk.store.dir(ehcache的配置目錄)
            絕對路徑(如:d:\\ehcache)
        檢視路徑方法:String tmpDir = System.getProperty("java.io.tmpdir");
     -->
    <diskStore path="java.io.tmpdir" />

    <!--
        defaultCache:預設的快取配置資訊,如果不加特殊說明,則所有物件按照此配置項處理
        maxElementsInMemory:設定了快取的上限,最多儲存多少個記錄物件
        eternal:代表物件是否永不過期 (指定true則下面兩項配置需為0無限期)
        timeToIdleSeconds:最大的發呆時間 /秒
        timeToLiveSeconds:最大的存活時間 /秒
        overflowToDisk:是否允許物件被寫入到磁碟
        說明:下列配置自快取建立起600秒(10分鐘)有效 。
        在有效的600秒(10分鐘)內,如果連續120秒(2分鐘)未訪問快取,則快取失效。
        就算有訪問,也只會存活600秒。
     -->
    <defaultCache maxElementsInMemory="10000" eternal="false"
                  timeToIdleSeconds="600" timeToLiveSeconds="600" overflowToDisk="true" />

    <cache name="userCache" maxElementsInMemory="10000" eternal="false"
                  timeToIdleSeconds="120" timeToLiveSeconds="600" overflowToDisk="true" />

</ehcache>

開啟快取支援

在 Spring Boot 中使用 @EnableCaching 開啟快取支援。

@EnableCaching
@SpringBootApplication
public class SpringbootCacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootCacheApplication.class, args);
    }
}

Service層

建立一個服務類,新增@CacheConfig(cacheNames = {“userCache”})註解設定ehcache的名稱,這個名稱必須在ehcache.xml已配置 。

@Service
@CacheConfig(cacheNames = {"userCache"})
public class UserService {

}

首先,我們先來講解下 @Cacheable 註解。@Cacheable 在方法執行前 Spring 先檢視快取中是否有資料,如果有資料,則直接返回快取資料;若沒有資料,呼叫方法並將方法返回值放進快取。此處的value不是必需的,你可以使用@CacheConfig(cacheNames = {“userCache”})註解來統一指定value的值,這時可省略value,如果你在方法依舊寫上了value,那麼依然以方法的value值為準。注意:此處的User實體類一定要實現序列化,否則會報java.io.NotSerializableException異常。

@Cacheable(key = "#id")
public User findUser(int id) {
     return userDao.findUser(id);
}

@CachePut註解的作用主要針對方法配置,能夠根據方法的請求引數對其結果進行快取,和@Cacheable不同的是,它每次都會觸發真實方法的呼叫 。簡單來說就是使用者更新快取資料。但需要注意的是該註解的value和key必須與要更新的快取相同,也就是與@Cacheable 相同。

@CachePut(key = "#id")
public User add(int id,String name,int age) {
   User user = new User(id, name, age);
   userDao.add(user);
   return user;
}
@CachePut(key = "#id")
public User update(String name,int age, int id) {
   User user = new User(id, name, age);
   userDao.update(user);
   return user;
}

@CacheEvict 將一條或多條資料從快取中刪除, 主要用於刪除方法,用來從快取中移除相應資料。

 @CacheEvict(key = "#id")
public int delete(int id) {
    return userDao.delete(id);
}

Controller層

為了展現效果,我們先定義一組簡單的 RESTful API 介面進行測試。

@RestController
@RequestMapping("/user/cache")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping(value = "/list")
    public List<User> findUserList() {
        return userService.findUserList();
    }

    @GetMapping(value = "/{id}")
    public User findUser(@PathVariable("id") int id) {
        return userService.findUser(id);
    }

    @PutMapping(value = "/{id}")
    public String updateAccount(@PathVariable("id") int id, @RequestParam(value = "name", required = true) String name,
                                @RequestParam(value = "age", required = true) int age) {
        if (0 < userService.update(name, age, id)) {
            return "success";
        } else {
            return "fail";
        }
    }

    @DeleteMapping(value = "/{id}")
    public String delete(@PathVariable(value = "id") int id) {
        if (0 < userService.delete(id)) {
            return "success";
        } else {
            return "fail";
        }
    }

    @PostMapping(value = "/add")
    public String postAccount(@RequestParam(value = "id") int id, @RequestParam(value = "name") String name,
                              @RequestParam(value = "age") int age) {
        if (0 < userService.add(id, name, age)) {
            return "success";
        } else {
            return "fail";
        }
    }

}

測試

  • 多次呼叫查詢介面
    在這裡插入圖片描述
    檢視日誌資訊
    在這裡插入圖片描述
    由上圖可知,只打印了一條日誌資訊,這說明快取起了作用。
  • 呼叫儲存介面,再呼叫查詢介面
    在這裡插入圖片描述
    在這裡插入圖片描述
    檢視日誌資訊
    在這裡插入圖片描述由上圖可知,只打印了一條日誌資訊,這說明快取起了作用。

擴充套件閱讀

如果想更深入理解 Spring 的 Cache 機制,小編推薦一篇不錯的文章。
Spring Cache 抽象詳解

原始碼下載:https://github.com/chenjary/SpringBoot