springboot使用緩存(redis版)

Springboot中緩存推薦使用注解方式

參考:https://blog.csdn.net/wujiaqi0921/article/details/79123873

摘要

1.@Cacheable

@Cacheable可以標(biāo)記在一個(gè)方法上,也可以標(biāo)記在一個(gè)類上。當(dāng)標(biāo)記在一個(gè)方法上時(shí)表示該方法是支持緩存的,當(dāng)標(biāo)記在一個(gè)類上時(shí)則表示該類所有的方法都是支持緩存的。

對(duì)于一個(gè)支持緩存的方法,Spring會(huì)在其被調(diào)用后將其返回值緩存起來(lái),以保證下次利用同樣的參數(shù)來(lái)執(zhí)行該方法時(shí)可以直接從緩存中獲取結(jié)果,而不需要再次執(zhí)行該方法。

Spring在緩存方法的返回值時(shí)是以鍵值對(duì)進(jìn)行緩存的,值就是方法的返回結(jié)果,至于鍵的話,Spring又支持兩種策略,默認(rèn)策略和自定義策略,需要注意的是當(dāng)一個(gè)支持緩存的方法在對(duì)象內(nèi)部被調(diào)用時(shí)是不會(huì)觸發(fā)緩存功能的。

@Cacheable可以指定三個(gè)屬性,value、key和condition。

  • value:緩存的名稱,在 spring 配置文件中定義,必須指定至少一個(gè)。如@Cacheable(value=”mycache”) 或者@Cacheable(value={”cache1”,”cache2”}
  • key:緩存的 key,可以為空,如果指定要按照 SpEL 表達(dá)式編寫,如果不指定,則缺省按照方法的所有參數(shù)進(jìn)行組合。如@Cacheable(value=”testcache”,key=”#userName”)
  • condition:緩存的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才進(jìn)行緩存。如@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

注:除了上述使用方法參數(shù)作為key之外,Spring還為我們提供了一個(gè)root對(duì)象可以用來(lái)生成key。通過(guò)該root對(duì)象我們可以獲取到以下信息。

  • @Cacheable(cacheResolver=”MyCacheResolver”)執(zhí)行緩存解析器
  • @Cacheable(cacheManager=”“)執(zhí)行緩存管理器,默認(rèn)使用currentMapCacheManager
  • @Cacheable(cacheNames=”“)指定緩存的名稱
  • @Cacheable(keyGenerator=”“)在未指定key時(shí)指定緩存key值的生成器
  • @Cacheable(unless=”“) 過(guò)濾不需要緩存的值,支持spEl表達(dá)式。

    public User findById(String id) {
        System.out.println("執(zhí)行數(shù)據(jù)庫(kù)查詢方法");
        return userDao.findById(id);
    }

2.@CachePut

在支持Spring Cache的環(huán)境下,對(duì)于使用@Cacheable標(biāo)注的方法,Spring在每次執(zhí)行前都會(huì)檢查Cache中是否存在相同key的緩存元素,如果存在就不再執(zhí)行該方法,而是直接從緩存中獲取結(jié)果進(jìn)行返回,否則才會(huì)執(zhí)行并將返回結(jié)果存入指定的緩存中。

@CachePut也可以聲明一個(gè)方法支持緩存功能。與@Cacheable不同的是使用@CachePut標(biāo)注的方法在執(zhí)行前不會(huì)去檢查緩存中是否存在之前執(zhí)行過(guò)的結(jié)果,而是每次都會(huì)執(zhí)行該方法,并將執(zhí)行結(jié)果以鍵值對(duì)的形式存入指定的緩存中。
@CachePut也可以標(biāo)注在類上和方法上。使用@CachePut時(shí)我們可以指定的屬性跟@Cacheable是一樣的。

    @CachePut(value = "user", key = "#id", condition = "#id != '321'")
    public User findById(String id) {
        System.out.println("執(zhí)行數(shù)據(jù)庫(kù)查詢方法");
        return userDao.findById(id);
    }

3.@CacheEvict

@CacheEvict是用來(lái)標(biāo)注在需要清除緩存元素的方法或類上的。當(dāng)標(biāo)記在一個(gè)類上時(shí)表示其中所有的方法的執(zhí)行都會(huì)觸發(fā)緩存的清除操作。

@CacheEvict可以指定的屬性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的語(yǔ)義與@Cacheable對(duì)應(yīng)的屬性類似。即value表示清除操作是發(fā)生在哪些Cache上的(對(duì)應(yīng)Cache的名稱);key表示需要清除的是哪個(gè)key,如未指定則會(huì)使用默認(rèn)策略生成的key;condition表示清除操作發(fā)生的條件。

下面我們來(lái)介紹一下新出現(xiàn)的兩個(gè)屬性allEntries和beforeInvocation。

  • allEntries:是否清空所有緩存內(nèi)容,缺省為 false,如果指定為 true,則方法調(diào)用后將立即清空所有緩存。如:@CachEvict(value=”testcache”,allEntries=true)
  • beforeInvocation:是否在方法執(zhí)行前就清空,缺省為 false,如果指定為 true,則在方法還沒(méi)有執(zhí)行的時(shí)候就清空緩存,缺省情況下,如果方法執(zhí)行拋出異常,則不會(huì)清空緩存。如:@CachEvict(value=”testcache”,beforeInvocation=true)
    allEntries指定為true時(shí),則會(huì)清楚所有緩存。
    其他參數(shù)和@Cacheable相同
    @CacheEvict(value = "user", key = "#id")
    public void deleteUserById(String id) {

    }

4.@Caching

@Caching注解可以讓我們?cè)谝粋€(gè)方法或者類上同時(shí)指定多個(gè)Spring Cache相關(guān)的注解。其擁有三個(gè)屬性:cacheable、put和evict,分別用于指定@Cacheable、@CachePut和@CacheEvict。使用如下

    @Caching(cacheable = {@Cacheable(value = "user", key = "#id", condition = "#id != '123'"),
            @Cacheable(value = "user", key = "#id", condition = "#id != '321'")}
    )
    public User findById(String id) {
        System.out.println("執(zhí)行數(shù)據(jù)庫(kù)查詢方法");
        return userDao.findById(id);
    }

在上面我們沒(méi)有沒(méi)使用指定的緩存解析器,以及key生成器。那么我們?nèi)绾蝸?lái)實(shí)現(xiàn)自己的解析器,緩存管理類或者key生成器呢?我們可以通過(guò)實(shí)現(xiàn)org.springframework.cache.interceptor.KeyGenerator接口實(shí)現(xiàn)自己想要的主鍵生成器,通過(guò)org.springframework.cache.interceptor.CacheResolver接口來(lái)實(shí)現(xiàn)自己的緩存解析器。在這里就不進(jìn)行代碼展示了。
這里還需要提到@CacheConfig用于指定類全局配置。

另外,代碼行級(jí)使用,我封裝了個(gè)工具類

功能隨用隨增加,先提供基本的常用方法

package com.qdzklt.rdm.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Collection;

/**
 * 緩存操作工具類
 */
@Component
public class CacheUtil {

    private static RedisTemplate redisTemplate;

    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        CacheUtil.redisTemplate = redisTemplate;
    }

    /**
     * 獲得RedisTemplate
     *
     * @return RedisTemplate
     */
    public static RedisTemplate getRedisTemplate() {
        return redisTemplate;
    }

    /**
     * 是否包含某個(gè)key
     *
     * @param key key
     * @return booble
     */
    public static Boolean hasKey(Object key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 添加或更新
     *
     * @param key   鍵
     * @param value 值
     */
    public static void set(Object key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 獲取
     *
     * @param key 鍵
     */
    public static Object get(Object key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 刪除
     *
     * @param key 鍵
     */
    public static void delete(Object key) {
        redisTemplate.delete(key);
    }

    /**
     * 刪除
     *
     * @param keys 鍵集合
     */
    public static void delete(Collection keys) {
        redisTemplate.delete(keys);
    }

}
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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