簡介:
Spring 3.1中開始對緩存提供支持,核心思路是對方法的緩存,當開發者調用一個方法時,將方法的參數和返回值作為key/value緩存起來,當再次調用該方法時,如果緩存中有數據,就直接從緩存中獲取,否則再去執行該方法。但是,Spring 中並未提供緩存的實現,而是提供了-套緩存API,開發者可以自由選擇緩存的實現。
目前Spring Boot支持的緩存有如下幾種::
JCache (JSR-107)
EhCache 2.x
Hazelcast
Infinispan
Couchbase
Redis
Caffeine
Simple
使用:
pom.xml
<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-data-redis</artifactId> </dependency>
Encache配置文件:ehcache.xml
這是一個常規的Ehcache 配置文件,提供了兩個緩存策略,一個是默認的,另一個名為book _cache。
其中,name表示緩存名稱:
maxElementsInMemory 表示緩存最大個數:
etemal 表示緩存對象是否永久有效,一旦設置了永久有效,timcout 將不起作用:
timeToldleSeconds 表示緩存對象在失效前的允許閑置時間(單位:秒),當etermal對象不是永久有效時,該屬性才生效:
timeToLiveSeconds表示緩存對象在失效前允許存活的時間(單位:秒),當eternal-false對象不是永久有效時,該屬性才生效:
overflowToDisk 表示當內存中的對象數量達到maxElementsInMemory時,Eheache 是否將對象寫到磁盤中:
diskxpiryTheadntervalseconds 表示磁盤失效線程運行時間間隔。
<ehcache> <diskStore path="java.io.tmpdir/cache"/> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="false" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" /> <cache name="book_cache" maxElementsInMemory="10000" eternal="true" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" diskPersistent="true" diskExpiryThreadIntervalSeconds="10"/> </ehcache>
開啟緩存:@EnableCaching注解
@SpringBootApplication @EnableCaching public class CacheApplication { public static void main(String[] args) { SpringApplication.run(CacheApplication.class, args); } }
創建實體類和service
public class Book implements Serializable { private Integer id; private String name; private String author; 。。。。。 }
@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"); } }
在Service層上添加@CacheConfig注解指明使用的緩存的名字,這個配置可選,若不使用@CacheConfig注解,則直接在@Cacheable注解中指明緩存名字。
在getBookById方法上添加@Cacheable注解表示對該方法進行緩存,默認情況下,緩存的key是方法的參數,緩存的value是方法的返回值。當開發者在其他類中調用該方法時,首先會根據調用參數查看緩存中是否有相關數據,若有,則直接使用緩存數據,該方法不會執行,否則執行該方法,執行成功后將返回值緩存起來,但若是在當前類中調用該方法,則緩存不會生效
@Cacheable注解中還有一個屬性condition用來描述緩存的執行時機,例如@Cacheable(condition= "#id%2= =0")表示當id對2取模為0時才進行緩存,否則不緩存。
如果開發者不想使用默認的key,也可以自定義key,key = "#book.id"表示緩存的key為參數book對象中id 的值,key = "#id"表示緩存的key為參數id.
除了這種使用參數定義key的方式之外,Spring 還提供了一個root對象用來生成key,如表。
@CachePut注解一般用於數據更新方法上,與@Cacheable 注解不同,添加了@CachePut注解的方法每次在執行時都不去檢查緩存中是否有數據,而是直接執行方法,然后將方法的執行結果緩存起來,如果該key對應的數據已經被緩存起來了,就會覆蓋之前的數據,這樣可以避免再次加載數據時獲取到臟數據。同時,@CachePut具有和@Cacheable類似的屬性,這里不再贅述。
@CacheEvict注解一般用於刪除方法上,表示移除一個key對應的緩存。@CacheEvict注解有兩個特殊的屬性: allEntries和beforeInvocation, 其中allEntries表示是否將所有的緩存數據都移除,默認為false, beforeInvocation表示是否在方法執行之前移除緩存中的數據,默認為false,即在方法執行之后移除緩存中的數據。
測試:
@RunWith(SpringRunner.class) @SpringBootTest public class CacheApplicationTests { @Autowired BookDao bookDao; @Test public void contextLoads() { 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); } }
控制台:
getBookById
deleteBookById
getBookById
b3:Book{id=1, name='三國演義', author='羅貫中'}
updateBookById b4:Book{id=1, name='三國演義', author='羅貫中'}