SpringBoot淺析緩存機制之Ehcache 2.x應用
介紹
Spring 3.1 中開始對緩存提供支持,核心思路是對方法的緩存,當開發者調用一個方法時,將方法的參數和返回值作為 key/value 緩存起來,當再次調用改方法時,如果緩存中有數據,就直接從緩存中獲取,否則再去執行該方法。但是,Spring 中並未提供緩存的實現,而是提供瞭一套緩存 API ,開發者可以自由選擇緩存的實現,目前 Spring Boot 支持的緩存有如下幾種:
- JCache(JSR-107)
- EhCache 2.x
- Hazelcast
- Infinispan
- Couchbase
- Redis
- Caffeine
- Simple
此處隻介紹常用的緩存實現 Ehcache 2.x 和 Redis,由於 Spring 早已將緩存領域統一,因此無論使用哪種緩存實現,不同的隻是緩存配置,開發者使用的緩存註解是一致的(Spring 緩存註解和各種緩存實現的關系就像 JDBC 和各種數據庫驅動的關系一樣)。
Ehcache 2.x 緩存
Ehcache 緩存在Java開發領域久負盛名,在Spring Boot 中,隻需要一個配置文件就可以將 Ehcache 集成到項目中。步驟如下:
1. 創建項目添加緩存依賴
創建 Spring Boot 項目,添加 spring-boot-starter-cache 依賴以及 Ehcache 依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
2. 添加緩存配置文件
如果 Ehcache 的依賴存在,並且在 classpath 下有一個名為 echache.xml 的 Ehcache 配置文件,那麼 EhCacheCacheManager 將會自動作為緩存的實現。因此,在 resources 目錄下創建 ehcache.xml 文件作為 Ehcache 緩存的配置文件,如下:
<ehcache> <diskStore path="java.io.tmpdir/cache"/> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="false" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" /> <!-- name:緩存名稱 maxElementsInMemory:緩存最大個數 eternal:緩存對象是否永久有效。一旦設置瞭永久有效,timeout將不起作用 timeToIdleSeconds:緩存對象在失效前允許閑置時間(秒),當eternal為false時生效 timeToLiveSeconds:緩存對象在失效前允許存活的時間(秒),當eternal為false時生效 overflowToDisk:當內存中的對象數量達到maxElementsInMemory時, Ehcache 是否將對象寫到磁盤中 diskExpiryThreadIntervalSeconds:磁盤失效線程運行時間間隔 --> <cache name="book_cache" maxElementsInMemory="10000" eternal="true" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" diskPersistent="true" diskExpiryThreadIntervalSeconds="600"/> </ehcache>
這是一個常規的 Ehcache 配置文件,提供瞭兩個緩存策略,一個是默認的,另一個名為 book_cache 。還有更為詳細的 Ehcache 配置,此處不再一一介紹。如果開發者想自定義 Ehcache 配置文件的名稱和位置,可以在 application.properties 中添加如下配置:
spring.cache.ehcache.config=classpath:ehcache2.xml
3. 開啟緩存
在項目的入口類添加 @EnableCaching 註解開啟緩存,如下
@SpringBootApplication @EnableCaching public class CacheApplication { public static void main(String[] args) { SpringApplication.run(CacheApplication.class, args); } }
4. 創建 BookDao
Book
public class Book implements Serializable { private Integer id; private String name; private String author; @Override public String toString() { return "Book{" + "id=" + id + ", name='" + name + '\'' + ", author='" + author + '\'' + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } }
BookDao
@Repository @CacheConfig(cacheNames = "book_cache") public class BookDao { @Cacheable public Book getBookById(Integer id) { System.out.println("getBookById"); Book book = new Book(); book.setId(id); book.setName("三國演義"); book.setAuthor("羅貫中"); return book; } @CachePut(key = "#book.id") public Book updateBookById(Book book) { System.out.println("updateBookById"); book.setName("三國演義2"); return book; } @CacheEvict(key = "#id") public void deleteBookById(Integer id) { System.out.println("deleteBookById"); } }
代碼解釋:
在 BookDao 上添加 @CacheConfig 註解指明使用的緩存名字,這個配置可選,若不使用 @CacheConfig ,則直接在 @Cacheable 註解中指明緩存名字
在 getBookById 方法上添加 @Cacheable 註解表示對該方法進行緩存,默認情況下,緩存的key是方法的參數,緩存的 value 是方法的返回值。當開發者在其他類中調用該方法時,首先會根據調用參數查看緩存中是否有相關數據,若有,則直接使用緩存數據,該方法不會執行,否則執行該方法,執行成功後將返回值緩存起來,但若是在當前類中調用該方法,則緩存不會生效
@Cacheable 註解中還有一個屬性 condition 用來描述緩存的執行時機,例如 @Cacheable(“#id%2==0”) 表示 id 對 2 取模為0時才進緩存,否則不緩存
如果開發者不想使用默認到的 key ,也可以像 updateBookById 和 deleteBookById 一樣自定義 key,@CachePut(key = “#book.id”) 表示緩存的key 為參數book 對象中 id 的值,@CacheEvict(key = “#id”)表示緩存的key為參數id。除瞭這種使用參數定義 key 的方式外,Spring 還提供瞭一個 root 對象用來生成 key ,如圖
| 屬性名稱 | 屬性描述 | 用法示例 |
| — | — | — |
| methodName | 當前方法名 | #root.methodName |
| method | 當前方法對象 | #root.method.name |
| caches | 當前方法使用的緩存 | #root.caches[0].name |
| target | 當前被調用的對象 | #root.target |
| targetClass | 當前被調用的對象的class | #root.targetClass |
| args | 當前方法參數數組 | #root.args[0] |
如果這些 key 不能滿足開發需求,開發者也可以自定義緩存 key 的生成器 KeyGenerator,如下
@Component public class MyKeyGenerator implements KeyGenerator { @Override public Object generate(Object target, Method method, Object... params) { return Arrays.toString(params); } }
然後在 @Cacheable 註解中引用 MyKeyGenerator 實例即可
@Service @CacheConfig(cacheNames = "book_cache") public class BookDao { @Autowired MyKeyGenerator myKeyGenerator; @Cacheable(keyGenerator = "myKeyGenerator") public Book getBookById(Integer id) { System.out.println("getBookById"); Book book = new Book(); book.setId(id); book.setName("三國演義"); book.setAuthor("羅貫中"); return book; } @CachePut(key = "#book.id") public Book updateBookById(Book book) { System.out.println("updateBookById"); book.setName("三國演義2"); return book; } @CacheEvict(key = "#id") public void deleteBookById(Integer id) { System.out.println("deleteBookById"); } }
MyKeyGenerator 中的 generate 方法的參數分別是當前對象、當前請求的方法以及方法的參數,開發者可根據這些信息組成一個新的 key 返回,返回值就是緩存的 key。
- @CachePut 註解一般用於數據更新方法上,與 @Cacheable 註解不同,添加瞭 @CachePut 註解的方法每次在執行時都不去檢查緩存中是否有數據,而是直接執行方法,然後將方法的執行結果緩存起來,如果 key 對應的數據已經被緩存起來瞭,就會覆蓋之前的數據,這樣可以避免再次加載數據時獲取到臟數據。同時 @CachePut 具有和 @Cacheable 類似的屬性
- @CacheEvict 註解一般用於刪除方法上,表示移除一個 key 對應的緩存。@CacheEvict 註解由兩個特殊屬性:allEntries 和 beforeInvocation,其中 allEntries 表示是否將所有的緩存數據都移除,默認為 false,beforeInvocation 表示是否在方法執行之前移除緩存中的數據,默認為 false ,即在方法執行之後移除緩存中的數據 5. 創建測試類
5 .創建測試類
對 Service 中的方法進行測試
@RunWith(SpringRunner.class) @SpringBootTest public class CacheApplicationTests { @Autowired BookDao bookDao; @Test public void contextLoads() { bookDao.deleteBookById(1); bookDao.getBookById(1); bookDao.getBookById(1); bookDao.deleteBookById(1); Book b3 = bookDao.getBookById(1); System.out.println("b3:"+b3); Book b = new Book(); b.setName("三國演義"); b.setAuthor("羅貫中"); b.setId(1); bookDao.updateBookById(b); Book b4 = bookDao.getBookById(1); System.out.println("b4:"+b4); } }
執行該方法,控制臺打印日志如下:
deleteBookById
getBookById
deleteBookById
getBookById
b3:Book{id=1, name='三國演義', author='羅貫中'}
updateBookById
b4:Book{id=1, name='三國演義2', author='羅貫中'}
為瞭防止來回測試緩存的影響,這裡先執行刪除操作(同時也會刪除緩存)。然後執行瞭一次查詢,正常打印,接著又執行瞭一次查詢沒打印(直接讀取的緩存),然後執行刪除,接著再執行查詢正常打印(刪除操作也刪除瞭緩存),再接著執行更新操作(同時更新瞭緩存),最後再次查詢,打印更新後的數據。
到此這篇關於SpringBoot淺析緩存機制之Ehcache 2.x應用的文章就介紹到這瞭,更多相關SpringBoot Ehcache 2.x內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- SpringBoot淺析緩存機制之Redis單機緩存應用
- Spring Boot 整合持久層之JdbcTemplate
- Spring @Cacheable註解中key的使用詳解
- springboot ehcache 配置使用方法代碼詳解
- 詳談@Cacheable不起作用的原因:bean未序列化問題