4、spring-boot使用cache

spring cache

cache

緩存就是數(shù)據(jù)交換的緩沖區(qū)(稱作Cache),當(dāng)某一硬件要讀取數(shù)據(jù)時(shí),會(huì)首先從緩存中查找需要的數(shù)據(jù),如果找到了則直接執(zhí)行,找不到的話則從內(nèi)存中找。為什么使用緩存?究其原因就是緩存的讀寫(xiě)速度遠(yuǎn)快與磁盤,從減輕I/O開(kāi)銷和加快運(yùn)行速度方便都有很好的效果。那么我們緩存什么?哪些經(jīng)常讀取而又不經(jīng)常修改的數(shù)據(jù),那些數(shù)據(jù)量較大又很少修改的數(shù)據(jù)。

緩存更新策略
  1. FIFO(First In First Out) 隊(duì)列,先進(jìn)先出
  2. LFU(Least Frequently Used):最近最少使用算法,一定時(shí)間段內(nèi)使用次數(shù)(頻率)最少的那個(gè)被移除,借助計(jì)數(shù)器實(shí)現(xiàn);
  3. LRU(Least Recently Used):最久未使用算法,使用時(shí)間距離現(xiàn)在最久的那個(gè)被移除,借助計(jì)數(shù)器和隊(duì)列實(shí)現(xiàn);
  4. TTL(Time To Live ):存活期,即從緩存中創(chuàng)建時(shí)間點(diǎn)開(kāi)始直到它到期的一個(gè)時(shí)間段(不管在這個(gè)時(shí)間段內(nèi)有沒(méi)有訪問(wèn)都將過(guò)期)
  5. TTI(Time To Idle):空閑期,即一個(gè)數(shù)據(jù)多久沒(méi)被訪問(wèn)將從緩存中移除的時(shí)間。
搭建cache
  1. 添加項(xiàng)目maven依賴
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

2.啟動(dòng)類開(kāi)啟緩存功能

/**
 * 注解 @EnableCaching    開(kāi)啟緩存功能,放在配置類或啟動(dòng)類上
 *
 * @author hui.wang09
 * @since 14 November 2018
 */
@SpringBootApplication
@EnableCaching
public class Application {

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

3.使用cache注解添加緩存

/**
 * 使用spring cache
 *
 * 常用注解含義
 * 注解@CacheConfig,在類上設(shè)置當(dāng)前緩存的一些公共設(shè)置,比如緩存名稱;
 * 注解@Cacheable,作用在方法上,觸發(fā)緩存讀取操作。表明該方法的結(jié)果是可以緩存的,如果緩存存在,則目標(biāo)方法不會(huì)被調(diào)用,直接取出緩存。
 * 注解@CacheEvice,作用在方法上,觸發(fā)緩存失效操作,刪除緩存項(xiàng)或者清空緩存;
 * 注解@CachePut,作用在方法上,觸發(fā)緩存更新操作
 * 注解@Caching,作用在方法上,綜合上面的各種操作,在有些場(chǎng)景上,調(diào)用業(yè)務(wù)會(huì)觸發(fā)多種緩存操作。
 *
 *
 * @author hui.wang09
 * @since 14 November 2018
 */
@RestController
public class HelloController {

    private static Logger LOGGER = LoggerFactory.getLogger(HelloController.class);

    /**
     * 注解@Cacheable可以標(biāo)記在一個(gè)方法上,也可以標(biāo)記在一個(gè)類上。當(dāng)標(biāo)記在一個(gè)方法上時(shí)表示該方法是支持緩存的,
     * 當(dāng)標(biāo)記在一個(gè)類上時(shí)則表示該類所有的方法都是支持緩存的。@Cacheable可以指定三個(gè)屬性,value、key和condition。
     *
     * value:緩存的名稱,在 spring 配置文件中定義,必須指定至少一個(gè)。如@Cacheable(value=”mycache”)
     * key:緩存的 key,可以為空,如果指定要按照SpEL表達(dá)式編寫(xiě),如果不指定,則缺省按照方法的所有參數(shù)進(jìn)行組合。
     *      如@Cacheable(value=”mycache”,key=”#request”)
     * condition:緩存的條件,可以為空,使用 SpEL 編寫(xiě),返回 true 或者 false,只有為 true 才進(jìn)行緩存。
     *      如@Cacheable(value=”mycache”,condition=”#request.length()>2”)
     *
     */
    @RequestMapping("/hello")
    @Cacheable(value = "myEhCache", key = "#request")
    public String hello(@RequestParam String request) {
        LOGGER.info("==========================");
        LOGGER.info("執(zhí)行hello方法");
        LOGGER.info("==========================");
        return request;
    }

    /**
     * 注解@CachePut使用方式和@Cacheable是一樣的
     * Spring在每次執(zhí)行前都會(huì)檢查Cache中是否存在相同key的緩存元素,如果存在就不再執(zhí)行該方法,
     * 而是直接從緩存中獲取結(jié)果進(jìn)行返回,否則才會(huì)執(zhí)行并將返回結(jié)果存入指定的緩存中。
     *
     */
    @RequestMapping("/put")
    @CachePut(value = "mycache", key = "#request")
    public String put(@RequestParam String request) {
        LOGGER.info("==========================");
        LOGGER.info("執(zhí)行put方法");
        LOGGER.info("==========================");
        return request + 1;
    }
}
  • 此時(shí)訪問(wèn)hello接口第一次會(huì)執(zhí)行方法,打印日志,并將返回值緩存到緩存中,當(dāng)?shù)诙握{(diào)用hello方法,傳遞相同值的時(shí)候,不會(huì)執(zhí)行方法,會(huì)直接調(diào)用spring cache返回緩存中的值
  • 調(diào)用put方法,會(huì)執(zhí)行方法,打印日志,并將相同key的緩存值更新
注解詳解
  • @CacheConfig:在類上設(shè)置當(dāng)前緩存的一些公共設(shè)置,比如緩存名稱;
  • @Cacheable:作用在方法上,觸發(fā)緩存讀取操作。表明該方法的結(jié)果是可以緩存的,如果緩存存在,則目標(biāo)方法不會(huì)被調(diào)用,直接取出緩存。@Cacheable可以指定三個(gè)屬性:value、keycondition。
    value:緩存的名稱,在 spring 配置文件中定義,必須指定至少一個(gè)。如@Cacheable(value=”mycache”)
    key:緩存的 key,可以為空,如果指定要按照SpEL表達(dá)式編寫(xiě),如果不指定,則缺省按照方法的所有參數(shù)進(jìn)行組合。如@Cacheable(value=”mycache”,key=”#request”)
    condition:緩存的條件,可以為空,使用 SpEL 編寫(xiě),返回 true 或者 false,只有為 true 才進(jìn)行緩存。如@Cacheable(value=”mycache”,condition=”#request.length()>2”)
  • @CacheEvice:作用在方法上,觸發(fā)緩存失效操作,刪除緩存項(xiàng)或者清空緩存;
  • @CachePut:作用在方法上,觸發(fā)緩存更新操作
  • @Caching:作用在方法上,綜合上面的各種操作,在有些場(chǎng)景上,調(diào)用業(yè)務(wù)會(huì)觸發(fā)多種緩存操作
整合EhCache

1.添加maven依賴

        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
  1. 在application配置文件配置項(xiàng)目的緩存類型,并指定ehcache配置文件路徑
# 緩存類型(ehcache、redis)
spring.cache.type=ehcache
# ehcache 配置文件
spring.cache.ehcache.config=classpath:ehcache.xml
  1. 配置ehcache,在classpath路徑下創(chuàng)建ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

    <!-- 磁盤緩存位置 -->
    <diskStore path="java.io.tmpdir/ehcache"/>
    <!--
            磁盤存儲(chǔ):將緩存中暫時(shí)不使用的對(duì)象,轉(zhuǎn)移到硬盤,類似于Windows系統(tǒng)的虛擬內(nèi)存
            path:指定在硬盤上存儲(chǔ)對(duì)象的路徑
            path可以配置的目錄有:
                user.home(用戶的家目錄)
                user.dir(用戶當(dāng)前的工作目錄)
                java.io.tmpdir(默認(rèn)的臨時(shí)目錄)
                ehcache.disk.store.dir(ehcache的配置目錄)
                絕對(duì)路徑(如:d:\\ehcache)
            查看路徑方法:String tmpDir = System.getProperty("java.io.tmpdir");
    -->

    <!-- 默認(rèn)緩存 -->
    <defaultCache
            maxEntriesLocalHeap="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxEntriesLocalDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </defaultCache>

    <!--
    name:Cache 的唯一標(biāo)識(shí)
    maxElementsInMemory:內(nèi)存中允許存儲(chǔ)的最大的元素個(gè)數(shù)
    maxElementsOnDisk:硬盤最大緩存?zhèn)€數(shù),0代表無(wú)限個(gè)
    clearOnFlush:內(nèi)存數(shù)量最大時(shí)是否清除
    eternal:緩存對(duì)象是否永久有效,如果是,超時(shí)設(shè)置將被忽略
    overflowToDisk:內(nèi)存不足(超過(guò) maxElementsInMemory)時(shí),是否啟用磁盤緩存
    timeToIdleSeconds:設(shè)置對(duì)象在失效前的允許閑置時(shí)間(單位:秒)。僅當(dāng)eternal=false對(duì)象不是永久有效時(shí)使用,可選屬性,默認(rèn)值是0,也就是可閑置時(shí)間無(wú)窮大
    timeToLiveSeconds:緩存數(shù)據(jù)的生存時(shí)間(TTL),也就是一個(gè)元素從構(gòu)建到消亡的最大時(shí)間間隔值,這只能在元素不是永久駐留時(shí)有效,如果該值是0就意味著元素可以停頓無(wú)窮長(zhǎng)的時(shí)間
    diskPersistent:是否將緩存數(shù)據(jù)持久化到磁盤上,如果為 true,JVM 重啟數(shù)據(jù)依然存在。默認(rèn)值是false
    diskSpoolBufferSizeMB:這個(gè)參數(shù)設(shè)置DiskStore(磁盤緩存)的緩存區(qū)大小。默認(rèn)是30MB。每個(gè)Cache都應(yīng)該有自己的一個(gè)緩沖區(qū)
    diskExpiryThreadIntervalSeconds:磁盤失效線程運(yùn)行時(shí)間間隔,默認(rèn)是120秒
    memoryStoreEvictionPolicy:當(dāng)達(dá)到 maxElementsInMemory 限制時(shí),Ehcache 將根據(jù)指定策略清除內(nèi)存。默認(rèn)為 LRU(最近最少使用),其他策略有 FIFO(先進(jìn)先出),LFU(較少使用)
    -->

    <!-- 自定義緩存 -->
    <cache name="myEhCache"
           maxElementsInMemory="1000"
           eternal="false"
           timeToIdleSeconds="50"
           timeToLiveSeconds="50"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LRU"/>
</ehcache>
  1. 使用ehcache
/**
 * @author hui.wang09
 * @since 14 November 2018
 */
@RestController
@CacheConfig(cacheNames = "myEhCache")
public class EhCacheController {

    private static Logger LOGGER = LoggerFactory.getLogger(EhCacheController.class);

    @RequestMapping("/ehcache")
    @Cacheable(key = "#request")
    public String ehcacahe(@RequestParam String request) {
        LOGGER.info("==========================");
        LOGGER.info("執(zhí)行ehcache方法");
        LOGGER.info("==========================");
        return request;
    }
}

需要注意代碼中@CacheConfig寫(xiě)的cacheNames需要和ehcache配置的cache name一致
github連接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容