Spring,SpringBoot 啟用緩存、禁用緩存實現隨意切換


1.情景展示

  在實際開發過程中,我們為了減少對數據庫的頻繁訪問,會把不易更改的數據放到緩存中,減少對數據庫的訪問,以此,既能減少數據庫的操作次數,也能節省響應時間;

  但是,緩存同樣是一把雙刃劍,也會給我們帶來不便,比如:

  對於后端開發人員來說,我們習慣於直接操作數據庫完成對數據庫的修改,而不是通過前端發起請求,這樣,就會導致一個問題:

  不會觸發緩存更新操作,數據庫雖然已經改好,但是,緩存沒有得到更新;

  或者是,有的項目根本就不涉及修改操作,只負責讀取數據,這就不存在更新緩存的情形;

  而一旦數據庫發生修改,就無法保持數據同步,這就非常尷尬了,怎么辦?

2.情況分析

  我們通常使用的緩存注解是@CacheEnable,該注解只在第一次請求時會從數據庫拿到數據,並放到緩存當中,后續請求將直接從緩存讀取;

  鑒於spring啟用緩存,是通過使用注解@EnableCaching來完成的,我腦海里首先想到的是:

  能不能在配置文件中進行動態設置,換言之就是:將是否啟動緩存的決定權遷移到配置文件中,比如:application.yml中。

  事實證明,我想太多了,無法實現!

3.解決方案

  我們知道,spring的緩存只存在於項目運行期間,它不像redis,即使你把項目停了,緩存依然會存在;

  由此,就誕生了第一種解決方案:

  方案一:重啟項目 

  重啟項目,所有的緩存將不復存在。

  方案二:禁用緩存

  我們只要把使用注解@EnableCaching刪掉或者是注銷掉,重啟項目就OK啦。

  但是,這對於已經部署在Linux服務器下的項目而言,可操作性不強,我們還得替換class文件才行。

  方案三:手動觸發清除緩存操作

  可能,會有小伙伴說,設置緩存的失效時間不就完了,可以設置失效時間,但那是只有到指定時間后才會失效,不能滿足我們的及時性,總不能一直等到緩存失效,再干活吧? 

  我們可以創建控制器,向外提供接口,手動清除緩存,通過這種方式來間接實現緩存的清除操作,這樣,也不用重啟服務器,緩存也能接着用(重啟服務器的目的就是為了清除緩存)

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
/**
 * 清除緩存控制器
 * @description:
 * @author: Marydon
 * @date: 2020-12-16 12:51
 * @version: 1.0
 * @email: marydon20170307@163.com
 */
@Api("CacheController")
@ApiSupport(order = 266, author = "Marydon")
@Slf4j
// 必須作用在類上,不然只能校驗Null,不能校驗Empty
@Validated
@Controller
public class CacheController {

    // 注入緩存管理器
    @Resource
    private CacheManager cacheManager;

    @ApiOperation(value = "清除所有緩存", notes = "清空所有緩存")
    @ApiOperationSupport(author = "Marydon", order = 1)
    @GetMapping("/clearAll")
    public String clearAllCache() {
        cacheManager.getCacheNames().forEach(cacheName -> {
            cacheManager.getCache(cacheName).clear();
            log.info("緩存".concat(cacheName).concat("清理成功!"));
        });

        return "所有緩存清理完畢";
    }

    @ApiOperation(value = "清除指定緩存", notes = "根據入參清除緩存")
    @ApiOperationSupport(author = "Marydon", order = 10)
    // knife4j會將headers的值識別為響應數據類型
    @RequestMapping(value = "clear", method = {RequestMethod.GET, RequestMethod.POST}, headers = {"Accept=text/pain"})
    // 入參需要使用@RequestParam,否則請求會被spring攔截,進不來(請求數據類型為空)
    public String clearCacheByName(@ApiParam(value = "緩存名稱", required = true, example = "aaCache") @RequestParam @NotBlank(message = "緩存名稱不能為空") String cacheName) {
        Cache cache = cacheManager.getCache(cacheName);
        if (null == cache) return cacheName + "並不存在";

        cache.clear();
        log.info(cacheName + "緩存清理完畢");
        return cacheName + "緩存清理完畢";
    }
}

  上面提供了兩種清除緩存的方法,一種是清除所有緩存,另一種是清除指定緩存。  

4.測試

  調用使用緩存的地方,一般是從前端發起請求;

  初次請求,從數據庫拿數據;

  清空控制台,現在來二次請求;

  已經不再從數據庫獲取數據 

  清空控制台,仙子,我們來調用清空緩存操作:

  緩存清理成功

  此時,我們發起第三次觸發緩存的請求

  從數據庫讀取,這就證明了咱們的代碼生效了,搞定。 

5.bug修復

  2020-12-17

  上面的代碼存在一個問題:我們實際想返回字符串信息,但是實際上,springmvc會自動將字符串識別為路徑,這就非常尷尬,返回的就是404;

  如何讓springmvc不把它當成路徑,而是作為數據返回呢?

  這里提供三種實現方式:

  最古老的方式:返回字符流

  第二種:將@Controller替換成@RestController

  第三種:在接口方法上添加@ResponseBody 

 

寫在最后

  哪位大佬如若發現文章存在紕漏之處或需要補充更多內容,歡迎留言!!!

 相關推薦:

 


免責聲明!

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



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