SpringCache使用詳解

SpringCache

      • 1.新建測試項目SpringCache
      • 2.SpringCache整合redis
        • 2.1.@Cacheable
        • 2.2.@CacheEvict
        • 2.3.@Cacheput
        • 2.4.@Caching
        • 2.5.@CacheConfig
      • 3.SpringCache問題
      • 4.SpringCache實現多級緩存

1.新建測試項目SpringCache

引入依賴

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--Mysql數據庫驅動--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- MyBatis--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>

實體類

@Data
public class User {private Long id;private String name;private Integer age;}

mapper

@Mapper
public interface UserMapper extends BaseMapper<User> {}

application.yml

spring:datasource:url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

測試下沒問題就搭建完成,開始springcache的測試

2.SpringCache整合redis

spring cache官方文檔
spEl語法說明官方文檔

下面是以redis為例,其他緩存也是下面這些步驟,一般來說要把cache抽出成一個類,下面為了測試方便直接在controller里做

1.引入依賴

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

2.配置類

@EnableCaching //開啟緩存
@Configuration
public class CacheConfig {@Beanpublic CacheManager redisCacheManager(RedisConnectionFactory factory) {// 配置序列化(解決亂碼的問題),過期時間600秒RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()//過期時間.entryTtl(Duration.ofSeconds(600))//緩存key.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))//緩存組件value.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))//value不為空,為空報錯.disableCachingNullValues().computePrefixWith(cacheName -> cacheName + ":");RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();return cacheManager;}
}

3.application.yml

spring:datasource:url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driverredis:host: 127.0.0.1port: 6379password: 123456
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

4.controller

@RestController
@CacheConfig(cacheNames = "user", cacheManager = "redisCacheManager")
public class UserController {@AutowiredUserMapper userMapper;@GetMapping("/list")@Cacheable(key = "#root.method.name")public List<User> list() {return userMapper.selectList(null);}
}

5.訪問http://localhost:8080/list測試,數據被緩存到redis中了

2.1.@Cacheable

@Cacheable:觸發緩存填充。

注解屬性

注解屬性作用
value / cacheNames用于指定緩存的名稱,可以指定一個或多個緩存名稱
key用于指定緩存的鍵,可以使用 SpEL 表達式
condition用于指定一個條件,如果條件成立,則執行緩存
unless用于指定一個條件,如果條件不成立,則執行緩存
keyGenerator用于指定自定義的緩存鍵生成器
cacheManager用于指定自定義的緩存管理器
sync用于指定是否使用同步模式,當設置為 true 時,表示在方法執行時,阻塞其他請求,直到緩存更新完成

SpEL上下文數據

屬性名稱描述示例
methodName正在調用的方法的名稱#root.methodName
method正在調用的方法#root.method.name
target正在調用的目標對象#root.target
targetClass被調用目標的class#root.targetClass
args用于調用目標的參數#root.args[0]
caches當前被調用的方法使用的Cache#root.caches[0].name
result方法調用的結果#result
/*** 生成的緩存:myCache:qwer  value:"9999"* condition = "#param.length() > 3" 參數長度大于3進行緩存* unless = "#result == null"        結果等于null不進行緩存*/
@GetMapping("/getCachedValue")
@Cacheable(value = "myCache", key = "#param", condition = "#param.length() > 3", unless = "#result == null")
public String getCachedValue(@RequestParam("param") String param) {return "9999";
}

訪問:http://localhost:8080/getCachedValue?param=qwer測試,成功緩存,修改代碼return null;再測試,就不會進行緩存

/*** 可以緩存null值,但會亂碼,不影響使用* 緩存null值有兩種情況:* 1.return null;* 2.方法返回值為void*/
@GetMapping("/getUser")
@Cacheable(key = "#uid")
public User getUser(@RequestParam("uid") Long uid) {return userMapper.selectById(uid);
}

在這里插入圖片描述

2.2.@CacheEvict

@CacheEvict:觸發緩存逐出。

@GetMapping("/cacheEvict")
@CacheEvict(key = "'list'")//清除鍵為key的緩存
public void cacheEvict(){
}@GetMapping("/cacheEvictAll")
@CacheEvict(key = "'user'", allEntries = true)//清除user分區下的所有緩存
public void cacheEvictAll() {
}
2.3.@Cacheput

@CachePut:在不干擾方法執行的情況下更新緩存。

@GetMapping("/getUser")
@Cacheable(key = "#uid")
public User getUser(@RequestParam("uid") Long uid) {return userMapper.selectById(uid);
}@GetMapping("/update")
@CachePut(key = "#uid")
public User update(@RequestParam("uid") Long uid) {User user = new User();user.setId(uid);user.setName("lisi9999");userMapper.updateById(user);return user;
}

1.先http://localhost:8080/getUser?uid=2進行緩存
2.再http://localhost:8080/update?uid=2刷新緩存
3.再http://localhost:8080/getUser?uid=2查緩存
可以看到緩存被正確更新

注意:update方法返回值不能寫void,否則會觸發緩存空值的情況,緩存被刷新成亂碼了

2.4.@Caching

@Caching:重新組合要應用于方法的多個緩存操作。

/*** @Cacheable(key = "'allBooks'"):表示方法的返回值應該被緩存,使用 allBooks 作為緩存的鍵。* @CacheEvict(key = "#isbn"):表示在調用這個方法時,會清除緩存中鍵為 #isbn 的緩存項。* @CacheEvict(key = "'popularBooks'"):表示在調用這個方法時,會清除緩存中鍵為 'popularBooks' 的緩存項。*/
@Caching(cacheable = @Cacheable(key = "'allBooks'"),evict = {@CacheEvict(key = "#isbn"),@CacheEvict(key = "'popularBooks'")}
)
public String updateBookByIsbn(String isbn, String newTitle) {System.out.println("Updating book in the database for ISBN: " + isbn);// Simulate updating data in a databasereturn newTitle;
}
2.5.@CacheConfig

@CacheConfig:在類級別共享一些常見的緩存相關設置。

@CacheConfig(cacheNames = "user", cacheManager = "redisCacheManager")
public class UserCache {}

3.SpringCache問題

springCache的這些注解也受@Transactional的事務控制

@Transactional
@Cacheable(value = "myCache", key = "#id")
public String getCachedValueById(long id) {// 查詢底層數據源,如果緩存中沒有數據return fetchDataFromDataSource(id);
}

@Cacheable 注解被用于方法 getCachedValueById 上,而該方法也被 @Transactional 注解標記。這意味著當方法被調用時,緩存的操作和底層數據源的查詢將在同一個事務中進行。如果事務回滾(例如,由于異常的發生),緩存的操作也會被回滾,確保數據的一致性。

springcache的讀模式和寫模式什么意思,為什么說springcache解決了讀模式的緩存擊穿,緩存穿透,緩存雪崩問題,沒有解決寫模式的這些問題

讀模式和寫模式是緩存中常用的兩種操作方式,分別涉及到對緩存的讀取和寫入。

  1. 讀模式(Read-Through)
    讀模式是指在讀取數據時,首先嘗試從緩存中獲取數據。如果緩存中存在數據,則直接返回緩存的值,避免了對底層數據源(例如數據庫)的直接訪問。如果緩存中不存在數據,系統會查詢底層數據源,將查詢到的數據加載到緩存中,并返回給調用方。

Spring Cache 中的 @Cacheable 注解是典型的讀模式的代表。這樣的模式可以有效減輕對底層數據源的訪問壓力,提高系統性能。

  1. 寫模式(Write-Through)
    寫模式是指在對數據進行寫入或修改時,首先對底層數據源進行相應的操作,然后再更新或清空緩存。這樣確保了緩存和底層數據源的一致性。

Spring Cache 中的 @CachePut 和 @CacheEvict 注解是寫模式的代表。@CachePut 用于更新緩存,@CacheEvict 用于清除緩存。

關于 Spring Cache 解決問題的說法

關于 Spring Cache 解決了讀模式的緩存擊穿、緩存穿透、緩存雪崩問題的說法,主要是因為 Spring Cache 提供了對這些問題的解決方案:

  • 緩存擊穿: 通過 @Cacheable 注解的 sync 屬性,可以控制是否使用同步模式,以避免在高并發情況下多個線程同時查詢緩存失效的情況。

  • 緩存穿透: 通過 @Cacheable 注解的 cache-null-values 屬性,可以緩存空值,防止對于一些不存在的 key,頻繁查詢底層數據源。

  • 緩存雪崩: 通過設置緩存項的過期時間,以及使用隨機時間避免同時失效大量緩存項,可以減緩緩存雪崩問題的發生。

然而,寫模式中可能存在一些問題,比如緩存和底層數據源的一致性問題,因為在更新底層數據源和更新緩存之間存在一定的時間差。Spring Cache 沒有提供對寫模式問題的直接解決方案。在一些對數據一致性要求較高的場景中,可能需要結合其他手段(如數據庫事務、消息隊列等)來保證寫操作的一致性。

4.SpringCache實現多級緩存

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

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

相關文章

el-table如何動態增加列

el-table如何動態添加列&#xff1a; 1. 將數據從列表中拋出來直接放到對象中&#xff1a; data.forEach(el > {el.shipList.forEach(item > {el[item.FieldTag] item.DateTimeValue;});}); 2. 網頁&#xff1a; planFormList是列表內容&#xff0c;循環出來當做表頭。…

內褲洗衣機有用嗎?口碑最好的小型洗衣機

想必各位小伙伴都知道我們的貼身衣物&#xff0c;不可以與其他衣服一起在洗衣機中清洗&#xff0c;每次都需要把內衣褲挑選出來手洗&#xff0c;但是我們每天都要上廁所&#xff0c;難免會沾上污漬和細菌&#xff0c;我們在用手搓洗的過程中很難把細菌給清除掉&#xff0c;所以…

ios打包,證書獲取

HBuilderX 打包ios界面&#xff1a; Bundle ID(AppID)&#xff1a; 又稱應用ID&#xff0c;是每一個ios應用的唯一標識&#xff0c;就像一個人的身份證號碼&#xff1b; 每開發一個新應用&#xff0c;首先都需要先去創建一個Bundle ID Bundle ID 格式&#xff1a; 一般為&…

用Python寫了一個貪吃蛇大冒險小游戲

一、游戲簡介 1.1 游戲操作及游戲規則 &#xff08;1&#xff09;游戲開始后&#xff0c;通過鍵盤上下左右鍵控制貪吃蛇移動尋找食物&#xff1b; &#xff08;2&#xff09;貪吃蛇每吃一個食物&#xff0c;身長會增加一個單位&#xff1b; &#xff08;3&#xff09;在正常模…

CSDN文章保存為MD文檔(二)

免責聲明 文章僅做經驗分享用途&#xff0c;利用本文章所提供的信息而造成的任何直接或者間接的后果及損失&#xff0c;均由使用者本人負責&#xff0c;作者不為此承擔任何責任&#xff0c;一旦造成后果請自行承擔&#xff01;&#xff01;&#xff01; import sys sys.path.a…

【HarmonyOS】 低代碼平臺組件拖拽使用技巧之登錄組件

【關鍵字】 HarmonyOS、低代碼平臺、組件拖拽、登錄組件、代碼編輯器 1、寫在前面 前面我們介紹了低代碼中堆疊容器、滾動容器、網格布局、頁簽容器以及一些常用容器和組件的拖拽使用方法&#xff0c;本篇我們來介紹一個新的組件&#xff0c;這個組件是屬于業務組件——登錄組…

Modbus轉Profinet網關:PLC與天信流量計通訊的經典案例

無論您是PLC或工業設備的制造商&#xff0c;還是工業自動化系統的維護人員&#xff0c;可能會遇到需要將不同協議的設備連接組合并通訊的情況&#xff0c;Modbus和Profinet是現代工業自動化中常見的兩種通信協議&#xff0c;在工業控制領域中被廣泛應用。 在這種情況絕大多數會…

快速上手Banana Pi BPI-M4 Zero 全志科技H618開源硬件開發開發板

Linux[編輯] 準備[編輯] 1. Linux鏡像支持SD卡或EMMC啟動&#xff0c;并且會優先從SD卡啟動。 2. 建議使用A1級卡&#xff0c;至少8GB。 3. 如果您想從 SD 卡啟動&#xff0c;請確保可啟動 EMMC 已格式化。 4. 如果您想從 EMMC 啟動并使用 Sdcard 作為存儲&#xff0c;請確…

《微信小程序開發從入門到實戰》學習二十六

3.4 開發參與投票頁面 參與投票頁面同樣需要收集用戶提交的信息&#xff0c;哪個用戶在哪個投票選擇了什么選項&#xff0c;因此它也是一個表單頁面 3.4.1 如何獲取投票信息 假設用戶A在投票創建頁面后填了表單&#xff08;1.創建投票&#xff09;&#xff0c;用戶A 點了提交…

docker容器生成鏡像并上傳個人賬戶

登錄到 Docker Hub 賬戶&#xff1a; docker login這將提示你輸入你的 Docker Hub 賬戶名和密碼。 為容器創建鏡像 docker commit <容器名或容器ID> <你的用戶名>/<鏡像名:標簽>例子 docker commit my_container yourusername/my_image:latest推送鏡像到…

山西電力市場日前價格預測【2023-11-24】

日前價格預測 預測說明&#xff1a; 如上圖所示&#xff0c;預測明日&#xff08;2023-11-24&#xff09;山西電力市場全天平均日前電價為415.13元/MWh。其中&#xff0c;最高日前電價為685.26元/MWh&#xff0c;預計出現在18:00。最低日前電價為296.84元/MWh&#xff0c;預計…

Web實戰:基于Django與Bootstrap的在線計算器

文章目錄 寫在前面實驗目標實驗內容1. 創建項目2. 導入框架3. 配置項目前端代碼后端代碼 4. 運行項目 注意事項寫在后面 寫在前面 本期內容&#xff1a;基于Django與Bootstrap的在線計算器 實驗環境&#xff1a; vscodepython(3.11.4)django(4.2.7)bootstrap(3.4.1)jquery(3…

美國DDoS服務器:如何保護你的網站免遭攻擊?

?  在當今數字化時代&#xff0c;互聯網已經成為人們生活中不可或缺的一部分。隨著互聯網的普及和發展&#xff0c;網絡安全問題也日益嚴重。其中&#xff0c;DDoS攻擊是目前最常見和具有破壞性的網絡攻擊之一。那么&#xff0c;如何保護你的網站免遭DDoS攻擊呢?下面將介紹…

C#開發的OpenRA游戲之屬性Selectable(9)

C#開發的OpenRA游戲之屬性Selectable(9) 在游戲里,一個物品是否具有選中的能力,是通過添加屬性Selectable來實現的。當一個物品不能被用戶選取,那么就不要添加這個屬性。 這個屬性定義在下面這段描述里: ^Selectable: Selectable: SelectionDecorations: WithSpriteCon…

CSS畫一條線

<p style"border: 1px solid rgba(0, 0, 0, 0.1);"></p> 效果&#xff1a;

MATLAB中imbothat函數用法

目錄 語法 說明 示例 使用底帽和頂帽濾波增強對比度 imbothat函數的功能是對圖像進行底帽濾波。 語法 J imbothat(I,SE) J imbothat(I,nhood) 說明 J imbothat(I,SE) 使用結構元素 SE 對灰度或二值圖像 I 執行形態學底帽濾波。底帽濾波計算圖像的形態學閉運算&#…

蘋果手機內存滿了怎么清理?這里有你想要的答案!

手機內存不足是一個比較普遍的現象。由于現在手機應用程序的功能越來越強大&#xff0c;所以占用的內存也越來越大。同時用戶會在手機中存儲大量的數據&#xff0c;如照片、視頻、文檔等&#xff0c;這些都會占用大量的手機空間。那么&#xff0c;蘋果手機內存滿了怎么清理&…

C++數組中重復的數字

3. 數組中重復的數字 題目鏈接 牛客網 題目描述 在一個長度為 n 的數組里的所有數字都在 0 到 n-1 的范圍內。數組中某些數字是重復的,但不知道有幾個數字是重復的,也不知道每個數字重復幾次。請找出數組中任意一個重復的數字。 Input: {2, 3, 1, 0, 2, 5}Output: 2解題…

Altium Designer學習筆記10

再次根據圖紙進行布局走線&#xff1a; 這個MT2492 建議的布局走線。 那我這邊應該是盡量按照該圖進行布局&#xff1a; 其中我看到C1的電容的封裝使用的是電感的封裝&#xff0c;需要進行更換處理&#xff1a; 執行Validate Changes和Execute Changes操作&#xff0c;更新&a…

程序員最奔潰的瞬間

身為程序員哪一個瞬間讓你最奔潰&#xff1f; *程序員最奔潰的瞬間&#xff0c; 勇士&#xff1f; or 無知&#xff1f;