SpringBoot進階教程(五十三)整合Redis之@Cacheable、@CachePut、@CacheEvict的應用


在上一篇文章(《SpringBoot(二十四)整合Redis》)中,已經實現了Spring Boot對Redis的整合,既然已經講到Cache了,今天就介紹介紹緩存注解。各家互聯網產品現在數據量越來越大,其快速增長造成網絡擁塞和服務器超載,導致客戶訪問延遲增大,服務質量日益顯現出來。緩存技術被認為是減輕服務器負載、降低網絡擁塞、增強可擴展性的有效途徑之一。

v概念介紹

 Spring為我們提供了幾個注解來支持Spring Cache。其核心主要是@Cacheable和@CacheEvict。使用@Cacheable標記的方法在執行后Spring Cache將緩存其返回結果,而使用@CacheEvict標記的方法會在方法執行前或者執行后移除Spring Cache中的某些元素。下面我們將來詳細介紹一下Spring基於注解對Cache的支持所提供的幾個注解。

Spring Cache常見概念介紹

名稱 解釋
Cache 緩存接口,定義緩存操作。實現有:RedisCache、EhCacheCache、ConcurrentMapCache等
CacheManager 緩存管理器,管理各種緩存(cache)組件
@Cacheable 主要針對方法配置,能夠根據方法的請求參數對其進行緩存
@CacheEvict 清空緩存
@CachePut 保證方法被調用,又希望結果被緩存。
與@Cacheable區別在於是否每次都調用方法,常用於更新
@EnableCaching 開啟基於注解的緩存
keyGenerator 緩存數據時key生成策略
serialize 緩存數據時value序列化策略
@CacheConfig 統一配置本類的緩存注解的屬性

注解(@Cacheable/@CachePut/@CacheEvict)的主要參數

名稱 解釋 example
value 緩存的名稱,在 spring 配置文件中定義,必須指定至少一個 e.g.
@Cacheable(value=”mycache”) 或者
@Cacheable(value={”cache1”,”cache2”}
key 緩存的 key,可以為空,如果指定要按照 SpEL 表達式編寫,
如果不指定,則缺省按照方法的所有參數進行組合
e.g.
@Cacheable(value=”testcache”,key=”#id”)
condition 緩存的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,
只有為 true 才進行緩存/清除緩存
e.g.@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
unless 否定緩存。當條件結果為TRUE時,就不會緩存。 e.g.@Cacheable(value=”testcache”,unless=”#userName.length()>2”)
allEntries
(@CacheEvict )
是否清空所有緩存內容,缺省為 false,如果指定為 true,
則方法調用后將立即清空所有緩存
e.g.
@CachEvict(value=”testcache”,allEntries=true)
beforeInvocation
(@CacheEvict)
是否在方法執行前就清空,缺省為 false,如果指定為 true,
則在方法還沒有執行的時候就清空緩存,缺省情況下,如果方法
執行拋出異常,則不會清空緩存
e.g.
@CachEvict(value=”testcache”,beforeInvocation=true)

v准備工作

1.1 引入依賴pom.xml

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

激活啟動類注解@EnableCaching

SpringBoot進階教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的應用

v實戰演練

2.1 添加service層

package com.demo.service;

import com.demo.pojo.UserDetails;

/**
 * Created by toutou on 2019/1/20.
 */
public interface CacheService {
    UserDetails getUserDetailsByUid(int uid);

    UserDetails updateUserInfo(UserDetails userDetails);

    int delUserInfoById(int uid);
}
package com.demo.service;

import com.demo.dao.UserDetailsMapper;
import com.demo.pojo.UserDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * Created by toutou on 2019/1/20.
 */
@Service
public class CacheServiceImpl implements CacheService{

    @Autowired
    UserDetailsMapper userDetailsMapper;

    @Override
    @Cacheable(value = "user_details", key = "#uid", unless="#result == null")
    public UserDetails getUserDetailsByUid(int uid){
        System.out.println(" Cacheable 有請求過來了");
        UserDetails userDetails = userDetailsMapper.getUserDetailsByUid(uid);
        return userDetails;
    }

    @Override
    @CachePut(value = "user_details", key = "#user.id")
    public UserDetails updateUserInfo(UserDetails user){
        System.out.println(" CachePut 有請求過來了");
        if(userDetailsMapper.updateByPrimaryKeySelective(user) > 0) {
            // 這里也可以直接在updateByPrimaryKeySelective的方法里,修改后直接查詢出該記錄返回UserDetails實例,看需求。
            user = userDetailsMapper.getUserDetailsByUid(user.getId());
            return user;
        }else{
            return null;
        }
    }

    @Override
    @CacheEvict(value = "user_details", key = "#uid")
    public int delUserInfoById(int uid){
        System.out.println(" CacheEvict 有請求過來了");
        return userDetailsMapper.deleteByPrimaryKey(uid);
    }
}

unless="#result == null"是指當查詢為空時,不緩存,默認是空也會緩存。

2.2 添加CacheController

package com.demo.controller;

import com.demo.pojo.UserDetails;
import com.demo.service.CacheService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by toutou on 2019/1/20.
 */
@RestController
@Slf4j
public class CacheController {

    @Autowired
    CacheService cacheService;

    @RequestMapping(value = "/cache/getuserbyid")
    public UserDetails getUserDetailsByUid(int uid){
        try {
            return cacheService.getUserDetailsByUid(uid);
        }catch (Exception e){
            System.out.println(e.toString());
            return null;
        }
    }

    @RequestMapping(value = "/cache/updateuserinfo")
    public int updateUserInfo(int uid, String city){
        UserDetails userDetails = new UserDetails();
        userDetails.setId(uid);
        userDetails.setCity(city);
        userDetails = cacheService.updateUserInfo(userDetails);
        return userDetails == null ? 0 : userDetails.getUid();
    }

    @RequestMapping(value = "/cache/deluserinfobyid")
    public int delUserInfoById(int uid){
        return cacheService.delUserInfoById(uid);
    }
}

2.3 實現Serializable接口

SpringBoot進階教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的應用

v效果展示

3.1 Cacheable效果

當我們本地請求http://localhost:8081/cache/getuserbyid?uid=5接口時,可以看到控制台輸出Cacheable 有請求過來了,而后續再次請求該接口時,不會再輸出Cacheable 有請求過來了,這是因為直接走了緩存機制了,CacheServiceImpl的方法不再被調用。

SpringBoot進階教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的應用

通過Redis可以看到,user_details::5的記錄已被創建。

SpringBoot進階教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的應用

3.2 CachePut效果

當我們本地請求http://localhost:8081/cache/updateuserinfo?uid=5&city=首都 接口時,將更新數據庫和Redis中對應的字段值。

SpringBoot進階教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的應用

查詢接口,更新成功。控制台再次輸出Cacheable 有請求過來了

SpringBoot進階教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的應用

3.3 CacheEvict效果

當我們本地請求http://localhost:8081/cache/deluserinfobyid?uid=5 接口時,將刪除數據中和Redis中的數據。

SpringBoot進階教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的應用

v博客總結

Redis和@Cacheable、@CachePut、@CacheEvict結合使用,效果挺好,結合這篇和上篇文章(《SpringBoot(二十四)整合Redis》),可以嘗試着結合使用試試。

v源碼地址

https://github.com/toutouge/javademosecond/tree/master/hellospringboot


作  者:請叫我頭頭哥
出  處:http://www.cnblogs.com/toutou/
關於作者:專注於基礎平台的項目開發。如有問題或建議,請多多賜教!
版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
特此聲明:所有評論和私信都會在第一時間回復。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信
聲援博主:如果您覺得文章對您有幫助,可以點擊文章右下角推薦一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM