SpringBoot整合SpringCache緩存

SpringBoot整合SpringCache使用緩存

文章目錄

    • SpringBoot整合SpringCache使用緩存
    • 1.介紹
    • 2.SpringBoot整合
      • 1.導入xml依賴
      • 2.配置yml
      • 3.使用@EnableCaching啟用SpringCache
      • 4.@Cacheable
      • 5.@CachePut
      • 6.@CacheEvict
      • 7. @Caching
      • 8.@CacheConfig
    • 3.其他屬性配置
        • 1.`keyGenerator` 屬性
        • 2. `cacheManager` 屬性
        • 3.`cacheResolver` 屬性
        • 4.CacheManagerCustomizer

1.介紹

Spring Cache 提供了 CacheCacheManager 接口來統一管理不同的緩存技術。Cache 是緩存的抽象,CacheManager 負責管理多個 Cache 實例。Spring Cache 支持多種緩存實現,包括:

  • ConcurrentHashMap:默認的緩存實現,適用于簡單的本地緩存。
  • Redis:基于 Redis 的分布式緩存,適用于高并發場景。
  • Ehcache:符合 JSR-107 標準的緩存實現,支持二級緩存。
  • Caffeine:基于 Java 8 的高性能緩存庫,適用于需要高性能的場景。
  • JSR-107:支持 JSR-107 標準的緩存實現。

2.SpringBoot整合

本文基于springboot2.7版本測試

1.導入xml依賴

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

2.配置yml

spring:cache:cache-names: usertype: redisredis:#緩存前綴key-prefix: moshangshang_#是否啟用緩存統計信息。enable-statistics: false#是否允許緩存 null 值。cache-null-values: true#寫入 Redis 時是否使用 key prefix。use-key-prefix: trueredis:port: 6379host: 127.0.0.1password: rootlettuce:pool:max-active: 20 #連接池最大連接數(使用負值表示沒有限制)max-idle: 8   #連接池中的最大空閑連接min-idle: 5   # 連接池中的最小空閑連接timeout: 6000   #連接超時時長(毫秒)

如果cache-null-values:屬性啟用不能緩存null值,則緩存null時會拋出下方異常

java.lang.IllegalArgumentException: Cache 'user' does not allow 'null' values. Avoid storing null via '@Cacheable(unless="#result == null")' or configure RedisCache to allow 'null' via RedisCacheConfiguration.

cache-names屬性說明:

用于管理全的緩存key的全局配置,多個用逗號分割,比如 cache-names: user; use-key-prefix: false,則表示 @Cacheable(cacheNames = "user“)之類的注解不會使用key-prefix指定的緩存前綴,未配置的緩存名稱則采用默認全局配置

3.使用@EnableCaching啟用SpringCache

@SpringBootApplication
@EnableCaching
public class CacheApplication {public static void main(String[] args) {SpringApplication.run(CacheApplication.class, args);}
}

4.@Cacheable

@Cacheable 用于標記方法或類,表示該方法的返回值可以被緩存。
當方法執行前,Spring 會檢查緩存中是否存在相同 key 的緩存元素,如果存在則直接返回,否則執行方法并將結果存入緩存。

@Cacheable 的方法必須為 public:如果方法不是 public 的,Spring 無法通過代理來訪問緩存。

  • value 或 cacheNames:指定緩存的名稱,可以是單個字符串或字符串數組。
  • key:指定緩存的鍵,可以使用 SpEL 表達式來定義。
  • condition:指定緩存的條件,只有當條件為 true 時,才會從緩存中獲取結果。
  • unless:指定不將結果放入緩存的條件,即使結果存在,也不會被緩存。
  • sync:是否使用同步方式獲取緩存,避免多個線程同時執行方法。
  • 在某些場景下,需要確保緩存和數據庫的一致性,可以使用 @Cacheable 的 sync 屬性來啟用同步更新。且在多線程環境下確保只有一個線程執行查詢。
   /*** 根據id查詢用戶信息* 生成的key為moshangshang_user::38*/@GetMapping("/query/{id}")@Cacheable(cacheNames = "user",key = "#id",unless = "#result == null")public User getById(@PathVariable Long id){return userService.getById(id);}

5.@CachePut

@CachePut 用于標記方法,表示每次調用該方法時都會執行并存入緩存。

它總是會執行方法,并將結果添加到緩存中,不會檢查緩存中是否存在相同 key 的緩存元素。

  • value 或 cacheNames:指定緩存的名稱,可以是單個字符串或字符串數組。
  • key:指定緩存的鍵,可以使用 SpEL 表達式來定義。
  • condition:指定緩存的條件,只有當條件為 true 時,才會從緩存中獲取結果。
  • unless:指定不將結果放入緩存的條件,即使結果存在,也不會被緩存。
    @PostMapping("/save")@CachePut( key = "#user.id")public User updateUser(User user) {userService.saveOrUpdate(user);return user;}

6.@CacheEvict

@CacheEvict 用于標記方法,表示該方法執行時會清除緩存中的數據。

@CacheEvict 在方法執行期間拋出異常不會清空緩存:如果方法執行過程中拋出異常,@CacheEvict 的 allEntries 屬性不會生效。

它可以用于刪除緩存中的所有鍵值對,也可以用于清除特定的 key。

  • value 或 cacheNames:指定緩存的名稱,可以是單個字符串或字符串數組。
  • key:指定緩存的鍵,可以使用 SpEL 表達式來定義。
  • condition:指定緩存的條件,只有當條件為 true 時,才會從緩存中獲取結果。
  • beforeInvocation:是否在方法執行前清除緩存,為 true 時在方法執行前清除緩存。
  • allEntries:是否清除所有緩存條目,為 true 時清除所有緩存。
    /*** @CacheEvict 在方法執行期間拋出異常不會清空緩存:如果方法執行過程中拋出異常,@CacheEvict 的 allEntries 屬性不會生效。* @CacheEvict 用于標記方法,表示該方法執行時會清除緩存中的數據。* 它可以用于刪除緩存中的所有鍵值對,也可以用于清除特定的 key。* value 或 cacheNames:指定要清除的緩存名稱。* key:指定要清除的緩存鍵,可以使用 SpEL 表達式來定義。* allEntries:是否清除所有緩存條目,為 true 時清除所有緩存。* beforeInvocation:是否在方法執行前清除緩存,為 true 時在方法執行前清除緩存。* condition:指定清除緩存的條件,只有當條件為 true 時,才會清除緩存。*/@GetMapping("/delete/{id}")@CacheEvict(key = "#id", allEntries = false)public void deleteUser(@PathVariable Long id) {userService.removeById(id);}

7. @Caching

@Caching 是一個組合注解,可以同時應用多個其他注解,表示該方法會同時執行 @Cacheable、@CachePut 和 @CacheEvict 的操作。

@GetMapping("/save/caching")@Caching(cacheable = @Cacheable( key = "#user.id"),put = @CachePut( key = "#user.id"),evict = @CacheEvict( key = "#user.id"))public User saveUser(User user) {userService.save(user);return user;}

8.@CacheConfig

@CacheConfig 用于在類上設置公共的緩存配置,避免在每個方法上重復配置。

/*** @CacheConfig 用于在類上設置公共的緩存配置,避免在每個方法上重復配置。*/
@RestController
@AllArgsConstructor
@RequestMapping("cache")
@CacheConfig(cacheNames = "user")
public class CacheController {private final IUserService userService;@GetMapping("/query/{id}")@Cacheable(key = "#id",unless = "#result == null")public User getById(@PathVariable Long id){return userService.getById(id);}
}

3.其他屬性配置

1.keyGenerator 屬性

keyGenerator 屬性用于指定默認的鍵生成器(Key Generator)。如果在方法上未顯式指定 key 屬性,則使用該屬性值作為默認的鍵生成器。

1.配置生成器

@Configuration
public class CacheConfig {@Bean(name = "customKeyGenerator")public KeyGenerator keyGenerator() {return (target, method, params) -> method.getName() + "[" + Arrays.asList(params) + "]";}
}

等同于

    @Bean(name = "customKeyGenerator")public KeyGenerator keyGenerator() {return new KeyGenerator() {@Overridepublic Object generate(Object target, Method method, Object... params) {return method.getName() + "[" + Arrays.asList(params) + "]";}};}

2.使用

生成的key為moshangshang_user::getById[[39]]

    @Cacheable(unless = "#result == null",keyGenerator = "customKeyGenerator")public User getById(@PathVariable Long id){return userService.getById(id);}
2. cacheManager 屬性

cacheManager 屬性用于指定當前使用的 CacheManager 實現類的名稱。CacheManager 是 Spring 定義的一個接口,用于管理緩存(Cache)的創建和配置。Spring 提供了多種 CacheManager 的實現,例如 ConcurrentMapCacheManagerEhCacheCacheManagerCaffeineCacheManager 等。通過設置 cacheManager 屬性,可以指定使用哪種緩存管理器來管理緩存。

創建自定義的緩存管理器

@Configuration
public class CacheConfig {@Beanpublic ConcurrentMapCacheManager mapCacheManager() {return new ConcurrentMapCacheManager("user-map","user");}}

cacheManager() 方法返回了一個 ConcurrentMapCacheManager 實例,并且指定了緩存名稱。這個 CacheManager 將被用于管理名為 指定的緩存。

    /*** 執行的是mapCacheManager的緩存管理器*/@GetMapping("/manger/map/query/{id}")@Cacheable(cacheManager = "mapCacheManager")public User getRedisMangerById(@PathVariable Long id){return userService.getById(id);}
3.cacheResolver 屬性

cacheResolver 屬性用于指定一個自定義的 CacheResolver 實現。默認情況下,Spring 使用 SimpleCacheResolver 來解析緩存操作。通過自定義 CacheResolver,可以實現更復雜的緩存邏輯,例如根據方法名動態選擇緩存名稱或緩存管理器。

  • cacheManagercacheResolver 是互斥的:如果同時指定了 cacheManagercacheResolver,Spring 會拋出異常,因為 CacheResolver 的實現會忽略自定義的 CacheManager
  • 自定義 CacheResolver 的靈活性:通過自定義 CacheResolver,可以實現更靈活的緩存管理,例如根據方法名、參數或上下文動態選擇緩存名稱或緩存管理器 。
  • Spring 4.1 及以上版本:從 Spring 4.1 開始,@Cacheable@CachePut@CacheEvict 等注解的 value 屬性不再是強制性的,因為 CacheResolver 可以提供緩存名稱信息

自定義緩存解析器

getById方法取user緩存名稱下數據,其他取user-map下數據

public class CustomCacheResolver implements CacheResolver {private final ConcurrentMapCacheManager concurrentMapCacheManager;private final RedisCacheManager redisCacheManager;public CustomCacheResolver(ConcurrentMapCacheManager concurrentMapCacheManager, RedisCacheManager redisCacheManager) {this.concurrentMapCacheManager = concurrentMapCacheManager;this.redisCacheManager = redisCacheManager;}@Overridepublic Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {Collection<Cache> caches = new ArrayList<>();if (context.getTarget().getClass() == CacheController.class) {if (context.getMethod().getName().equals("getRedisById")) {caches.add(redisCacheManager.getCache("user"));}else {caches.add(concurrentMapCacheManager.getCache("user-map"));}}return caches;}
}

配置自定義緩存管理器并注冊緩存解析器

配置了自定義的CacheManager會導致yml里面的相關配置失效(任何一個都會,比如指定map的緩存管理器,yml配redis,則redis的配置也不生效)

    @Beanpublic ConcurrentMapCacheManager mapCacheManager() {return new ConcurrentMapCacheManager("user-map","user");}@Primary@Beanpublic RedisCacheManager redisCacheManager(RedisTemplate<String, Object> redisTemplate) {return RedisCacheManager.builder(Objects.requireNonNull(redisTemplate.getConnectionFactory())).cacheDefaults(RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)) // 設置默認緩存過期時間為10分鐘.disableCachingNullValues()) // 禁用緩存空值.withInitialCacheConfigurations(initialCacheConfigurations()) // 設置特定緩存的配置.build();}private Map<String, RedisCacheConfiguration> initialCacheConfigurations() {Map<String, RedisCacheConfiguration> initialConfigurations = new HashMap<>();// 設置特定緩存的過期時間initialConfigurations.put("user", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1)) // 設置特定緩存的過期時間為1小時.disableCachingNullValues());return initialConfigurations;}@Beanpublic CacheResolver customCacheResolver(ConcurrentMapCacheManager concurrentMapCacheManager,RedisCacheManager redisCacheManager) {return new CustomCacheResolver(concurrentMapCacheManager,redisCacheManager);}

測試

  /*** 執行的是RedisCacheManager的緩存管理器*/@GetMapping("/resolver/redis/query/{id}")@Cacheable(unless = "#result == null",cacheResolver = "customCacheResolver")public User getRedisById(@PathVariable Long id){return userService.getById(id);}/*** 執行的是ConcurrentMapCacheManager的緩存管理器*/@GetMapping("/resolver/map/query/{id}")@Cacheable(cacheNames = "user-map",unless = "#result == null",cacheResolver = "customCacheResolver")public User getMapCacheById(@PathVariable Long id){return userService.getById(id);}
4.CacheManagerCustomizer

CacheManagerCustomizer 是一個用于在緩存管理器初始化之前對其進行自定義配置的接口。通過實現該接口的 Bean,可以對緩存管理器進行定制,例如設置緩存名稱、是否允許緩存空值、設置緩存過期時間等。

  1. 自定義緩存配置CacheManagerCustomizer 允許在緩存管理器初始化之前對緩存進行配置,例如設置緩存名稱、過期時間、序列化方式等。這使得開發者可以針對不同的緩存需求進行靈活配置。
  2. 覆蓋默認配置:如果使用了 CacheManagerCustomizer,那么 application.ymlapplication.properties 中的緩存配置將不會生效,因為 CacheManagerCustomizer 會覆蓋默認的配置 。
  3. 支持多種緩存類型CacheManagerCustomizer 不僅適用于 ConcurrentMapCacheManager,還可以用于其他類型的緩存管理器,如 RedisCacheManagerCaffeineCacheManager 等。通過實現 CacheManagerCustomizer 接口,可以對不同類型的緩存管理器進行統一的配置 。
  4. 提供回調機制CacheManagerCustomizer 提供了一個 customize 方法,該方法會在緩存管理器初始化之前被調用,允許開發者對緩存管理器進行定制。例如,可以設置緩存名稱、允許或禁止緩存空值等 。
@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {return new CacheManagerCustomizer<ConcurrentMapCacheManager>() {@Overridepublic void customize(ConcurrentMapCacheManager cacheManager) {cacheManager.setCacheNames(Arrays.asList("user"));cacheManager.setAllowNullValues(false); // 禁用緩存空值}};
}@Beanpublic RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {return (builder) -> {builder.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)) // 默認過期時間為 10 分鐘.disableCachingNullValues()); // 禁用緩存空值};}

如果配置了自定義的緩存管理器(redisCacheManager),則CacheManagerCustomizer將不生效

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/87797.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87797.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87797.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

WPF學習筆記(20)Button與控件模板

Button與控件模板一、 Button默認控件模板詳解二、自定義按鈕模板一、 Button默認控件模板詳解 WPF 中的大多數控件都有默認的控件模板。 這些模板定義了控件的默認外觀和行為&#xff0c;包括控件的布局、背景、前景、邊框、內容等。 官方文檔&#xff1a;https://learn.mic…

藍天居士自傳(1)

藍天居士何許人&#xff1f; 藍天居士是我的筆名&#xff0c;也可以說是號。就好像李白號青蓮居士、歐陽修號六一居士一樣。筆者本名彭昊 —— 一個有不少重名重姓者的名字。 筆者小的時候上語文課&#xff0c;無論是小學、初中抑或是高中&#xff0c;都會有魯迅&#xff08;…

短劇系統開發定制全流程解析:從需求分析到上線的專業指南

一、短劇行業數字化趨勢與系統開發必要性在短視頻內容爆發式增長的時代背景下&#xff0c;短劇作為一種新興的內容形式正在迅速崛起。數據顯示&#xff0c;2023年中國短劇市場規模已突破300億元&#xff0c;用戶規模達到4.5億&#xff0c;年增長率超過200%。這一迅猛發展的市場…

getBoundingClientRect() 詳解:精準獲取元素位置和尺寸

getBoundingClientRect() 是 JavaScript 中一個強大的 DOM API&#xff0c;用于獲取元素在視口中的精確位置和尺寸信息。它返回一個 DOMRect 對象&#xff0c;包含元素的坐標、寬度和高度等關鍵幾何信息。 基本用法 const element document.getElementById(myElement); cons…

EXCEL 基礎技巧

來源&#xff1a;WPS 官網 初步了解WPS表格-WPS學堂https://www.wps.cn/learning/course/detail/id/635.html 1、格式刷 1.1使用格式刷隔行填充顏色。 首先設置部分表格顏色&#xff0c;選中此區域&#xff0c;雙擊點擊格式刷&#xff0c;然后選中其他表格區域。 這樣就可以…

【RK3568 編譯rtl8723DU驅動】

RK3568 編譯rtl8723DU驅動 編譯源碼1.解壓rtl8723du2.修改Makefile 驗證1.加載模塊2.開啟wifi 在驅動開發中&#xff0c;驅動的編譯與集成是實現設備功能的關鍵環節。本文聚焦于基于 RK3568 處理器平臺編譯 RTL8723DU WiFi/BT 二合一模塊驅動的完整流程&#xff0c;涵蓋源碼編譯…

基于Simulink的二關節機器人獨立PD控制仿真

文章目錄 理論模型仿真窗口控制函數目標函數仿真 本文是劉金琨. 機器人控制系統的設計與MATLAB仿真的學習筆記。 理論模型 對于二關節機器人系統&#xff0c;其動力學模型為 D ( q ) q C ( q , q ˙ ) q ˙ r D(q)\ddot qC(q,\dot q)\dot q r D(q)q?C(q,q˙?)q˙?r 式…

【技術架構解析】國產化雙復旦微FPGA+飛騰D2000核心板架構

本文就一款基于飛騰D2000核心板與兩片高性能FPGA的國產化開發主板進行技術解析&#xff0c;包括系統架構、主要硬件模塊、關鍵接口及軟件環境&#xff0c;重點闡述各子系統間的數據路徑與協同工作方式&#xff0c;旨在為行業內同類產品設計與應用提供參考。 隨著國產化要求的加…

Python 數據分析:計算,分組統計1,df.groupby()。聽故事學知識點怎么這么容易?

目錄1 示例代碼2 歡迎糾錯3 論文寫作/Python 學習智能體1 示例代碼 直接上代碼。 def grpby1():xls "book.xls"df pd.DataFrame(pd.read_excel(xls, engine"xlrd"))print(df)"""序號 分類 銷量0 1 文學 51 2 計算機…

【解決“此擴展可能損壞”】Edge瀏覽器(chrome系列通殺))擴展損壞?一招保留數據快速修復

引言 如果你想保留你的數據&#xff0c;敲重點&#xff1a;不要點擊修復&#xff0c;不要修復&#xff0c;不要修復 在使用 Microsoft Edge 瀏覽器時&#xff0c;您可能會遇到擴展程序顯示“此擴展程序可能已損壞”的提示&#xff0c;且啟用按鈕無法點擊。這一問題讓許多用戶感…

AI專業化應用加速落地,安全治理挑戰同步凸顯

7月2日&#xff0c;2025全球數字經濟大會在北京國家會議中心開幕。本屆大會以“建設數字友好城市”為主題&#xff0c;聚焦數字技術對城市發展的影響。開幕式上&#xff0c;一首完全由AI生成的MV成為焦點——從歌詞、譜曲、演唱到視頻制作全流程AI生成&#xff0c;展現人工智能…

Python統一調用多家大模型API指南

隨著大模型技術的快速發展&#xff0c;市場上出現了越來越多的LLM服務提供商&#xff0c;包括OpenAI、Anthropic、Google、百度、阿里云等。作為開發者&#xff0c;我們經常需要在不同的模型之間切換&#xff0c;或者同時使用多個模型來滿足不同的業務需求。本文將詳細介紹如何…

【ESP32】1.編譯、燒錄、創建工程

標題打開一個Hello world工程并燒錄 點擊環境搭建鏈接 遇到的問題&#xff1a; 1.ESP32在VSCODE中燒錄代碼時&#xff0c;跳出窗口&#xff0c;OPenOCD is not running ,do you want to launch it? 可能是OCD沒安裝&#xff0c;重新安裝 ESP-IDF試一下&#xff0c;在終端命令窗…

調參——optuna

它基于貝葉斯優化&#xff08;Bayesian Optimization&#xff09;思想&#xff0c;通過構建一個概率模型來預測超參數組合的性能&#xff0c;從而高效地探索超參數空間。相比傳統網格搜索&#xff08;Grid Search&#xff09;或隨機搜索&#xff08;Random Search&#xff09;&…

Redis的緩存擊穿和緩存雪崩

Redis緩存擊穿和緩存雪崩是兩種常見的緩存問題&#xff0c;它們都可能導致系統性能下降甚至崩潰。以下是對它們的詳細解釋&#xff1a;一、緩存擊穿定義緩存擊穿是指一個特定的緩存數據失效&#xff08;例如過期&#xff09;&#xff0c;而此時大量請求同時訪問這個數據&#x…

Python訓練營Day4

浙大疏錦行 Python訓練營Day4 內容&#xff0c;pandas處理表格信息&#xff1a; 查看表格統計信息&#xff1a; data.mean()data.mode()data.median() 查看表格信息&#xff1a; data.info()data.describe()data.isnull()data.head() 填充空缺列&#xff1a; 數值型&#xff…

React 基本介紹與項目創建

為什么使用 React 以及前端框架 工作原理 React 通過構建虛擬 DOM&#xff08;Virtual DOM&#xff09;來高效管理界面。當組件的狀態或屬性發生變化時&#xff0c;React 會重新渲染生成新的虛擬 DOM&#xff0c;并通過 Diff 算法找出新舊虛擬 DOM 樹之間的差異&#xff0c;最…

OpenCV CUDA模塊設備層-----“小于閾值設為零” 的圖像處理函數thresh_to_zero_func()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 OpenCV CUDA 模塊&#xff08;cudev&#xff09; 中的一個仿函數生成器&#xff0c;用于創建一個 “小于閾值設為零” 的圖像處理函數對象。 這個函…

數字圖像處理學習筆記

1-圖像處理基礎_嗶哩嗶哩_bilibili 輸出圖像像素點需要將圖象值要作類型轉換&#xff0c;轉成Int 圖像仿射變換 線性變換平移 線性變換&#xff1a; 1&#xff0c;變換前直線&#xff0c;變換后仍然直線 2&#xff0c;直線比例不變 3&#xff0c;直線到遠點的距離不變 仿射變…

用systemd管理GreatSQL服務詳解

用systemd管理GreatSQL服務詳解 1.GreatSQL服務文件 官網 greatsql.service 文件 [Unit] DescriptionGreatSQL Server Documentationman:mysqld(8) Documentationhttp://dev.mysql.com/doc/refman/en/using-systemd.html Afternetwork.target Aftersyslog.target [Install] …