SpringBoot整合緩存方式(Caffeine、Redis)
SpringBoot整合緩存
注解介紹
@EnableCaching
- 標記在CacheManager統(tǒng)一配置類
- 需要配合@Configuration使用
@Cachable
- 標記在需要使用緩存的實現(xiàn)類上,一般用于查詢操作。
- 當該方法輸入?yún)?shù)對應(yīng)的緩存數(shù)據(jù)不存在與緩存引擎中(類似Redis)時,則會自動生成相關(guān)緩存;若存在則直接獲取緩存結(jié)果。
@CachePut
- 標記在需要使用緩存的實現(xiàn)類上,一般用于更新操作。
- 無論如何都會執(zhí)行方法邏輯,更新到緩存引擎中
@CacheEvict
- 標記在需要使用緩存的實現(xiàn)類上,一般用于更新操作。
- 直接清除該緩存
優(yōu)缺點
- 優(yōu)點:可以快速的應(yīng)用緩存,不必要專業(yè)的中間件(例如:
CaffeineCache) - 缺點:無法精細的對緩存做業(yè)務(wù)處理,只能按照Spring整合緩存提供的邏輯執(zhí)行(例如:
RedisCache)。
依賴
<!--Spring Boot相關(guān)--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.6.8</version> </dependency> <!--CaffeineCache--> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>2.5.5</version> </dependency> <!--Redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.6.8</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.7.1</version> </dependency>
配置文件yml
spring:
redis:
host: 127.0.0.1
port: 6379整合Caffeine
步驟
1. 在自定義的CacheConfig中配置一個CaffeineCacheManager的@Bean

2. 在實現(xiàn)類中通過@Cachable進行標注(即表示使用哪個引擎CacheManager)

- 其中,value值對應(yīng)圖一中創(chuàng)建的緩存名稱,cacheManager(必填)對應(yīng)注入的
@Bean的名字, - 因為如果
CachesConfig中存在不同緩存引擎@Bean時(即多個CacheManager都來自一個接口),就會出現(xiàn)@Bean沖突的問題。 - 解決問題的關(guān)鍵就是使用
@Primary指定默認先加載哪個bean,或者就是當下的情況,直接指定cacheManager。
3. 測試緩存結(jié)果


代碼
CachesConfig配置類
@Configuration
@EnableCaching
public class CachesConfig {
@Bean(value = "getCaffeineCacheManager")
public CaffeineCacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
Cache<Object, Object> cache = Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.SECONDS)
.maximumSize(10_000)
.build();
cacheManager.registerCustomCache("demoCache",cache);
return cacheManager;
}
}
CachesController控制層
@RestController
@RequestMapping(value = "cachesController")
public class CachesController {
@Autowired
private CachesService cachesService;
@Autowired
@Qualifier("getCaffeineCacheManager")
private CaffeineCacheManager caffeineCacheManager;
@GetMapping("playCaffeineCaches")
public <T> T playCaffeineCaches() throws InterruptedException {
System.out.println(cachesService.getFromDB(1));
System.out.println(cachesService.getFromDB(1));
// 校驗緩存里的內(nèi)容~~~~
Cache demoCache = Objects.requireNonNull(caffeineCacheManager.getCache("demoCache"));
String s = demoCache.get(1, String.class);
System.out.println(s);
// 由于設(shè)定Caffeine的過期時間為5s,檢驗超時后緩存是否失效
TimeUnit.SECONDS.sleep(10);
s = demoCache.get(1, String.class);
System.out.println(s);
return (T) s;
}
}
CacheServiceImpl實現(xiàn)類
@Service
@CacheConfig(cacheNames = {"com.devilvan.config.CachesConfig"})
public class CacheServiceImpl implements CachesService {
@Cacheable(value = {"demoCache"}, cacheManager = "getCaffeineCacheManager", key = "#id")
@Override
public Object getFromDB(Integer id) {
System.out.println("模擬去db查詢~~~" + id);
return "hello cache...";
}
}
整合Redis緩存
步驟
1. 定義一個RedisTemplate的@Bean
如果不添加其他信息直接注入一個也行

2. 在自定義的CacheConfig中配置一個RedisCacheManager

3. 在實現(xiàn)類中標記@Cachable、@CachePut、@CacheEvict注解,對應(yīng)緩存的動作

參數(shù)
cacheManager
對應(yīng)配置類中定義的緩存引擎@Bean,CacheManager的實現(xiàn)類
cacheNames
自定義緩存的名字,這里如果定的名字為上圖中withCacheConfiguration()方法中的名字,則使用該方法參數(shù)中的配置
key
即緩存的對象ID,一般綁定方法參數(shù),當key值在緩存中不存在時,執(zhí)行邏輯并添加進緩存,存在則直接返回緩存的結(jié)果。
代碼
CachesConfig配置類
/**
* 自定義redisTemplate
*/
@Bean
public RedisTemplate<Object, Object> empRedisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// 轉(zhuǎn)換 格式
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new StringRedisSerializer());
return template;
}
/**
* 基于SpringBoot2 對 RedisCacheManager 的自定義配置
*/
@Bean("empRedisCacheManager")
@Primary
public RedisCacheManager empRedisCacheManager(@Autowired @Qualifier("empRedisTemplate") RedisTemplate<Object,Object> redisTemplate) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
.defaultCacheConfig()
// 設(shè)置key為String
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getStringSerializer()))
// 設(shè)置value 為自動轉(zhuǎn)Json的Object
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()))
// 不緩存null
.disableCachingNullValues()
// 緩存數(shù)據(jù)保存30s
.entryTtl(Duration.ofSeconds(30));
// 構(gòu)造一個redis緩存管理器
RedisCacheManager redisCacheManager = RedisCacheManager
.RedisCacheManagerBuilder
// Redis 連接工廠
.fromConnectionFactory(Objects.requireNonNull(redisTemplate.getConnectionFactory()))
// 設(shè)置默認緩存配置
.cacheDefaults(redisCacheConfiguration)
// 設(shè)置自定義緩存配置,緩存名為cache_user,它的過期時間為60s
.withCacheConfiguration("cache_user", redisCacheConfiguration.entryTtl(Duration.ofSeconds(60)))
// 上面默然緩存時間是1小時,但是可以根據(jù)cacheName來設(shè)置緩存時間
.withCacheConfiguration("cache_post", redisCacheConfiguration.entryTtl(Duration.ofSeconds(120)))
// 配置同步修改或刪除 put/evict
.transactionAware()
.build();
return redisCacheManager;
}
CachesController控制層
@GetMapping("playRedisCaches")
public <T> T playRedisCaches(@RequestParam("id") Integer id) {
System.out.println(cachesService.getDept(id));
System.out.println(cachesService.getDept(id));
return (T) null;
}
@PostMapping("updateRedisCaches")
public <T> T updateRedisCaches(@RequestParam("id") Integer id) {
System.out.println(cachesService.updateDept(id));
System.out.println(cachesService.getDept(id));
return (T) null;
}
@DeleteMapping("deleteRedisCaches")
public <T> T deleteRedisCaches(@RequestParam("id") Integer id) {
cachesService.deleteDept(id);
System.out.println(cachesService.getDept(id));
return (T) null;
}
CachesServiceImpl實現(xiàn)類
@Cacheable(cacheManager = "empRedisCacheManager",cacheNames = {"dept"},key = "#id")
@Override
public String getDept(Integer id) {
System.out.println("查詢"+ id +"號部門。" );
int i = new Random().nextInt(65535);
int hashCode = String.valueOf((id + i)).hashCode();
return "Do you like what you see?" + "-->" +hashCode;
}
@CachePut(cacheManager = "empRedisCacheManager",cacheNames = {"dept"},key = "#id")
@Override
public String updateDept(Integer id) {
System.out.println("更新"+ id +"號部門。" );
int i = new Random().nextInt(65535);
int hashCode = String.valueOf((id + i)).hashCode();
return "Do you like what you see?" + "-->" +hashCode;
}
@CacheEvict(cacheManager = "empRedisCacheManager",cacheNames = {"dept"},key = "#id")
@Override
public void deleteDept(Integer id) {
System.out.println("刪除"+ id +"號部門。" );
}
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java使用Instant時輸出的時間比預(yù)期少了八個小時
在Java中,LocalDateTime表示沒有時區(qū)信息的日期和時間,而Instant表示基于UTC的時間點,本文主要介紹了Java使用Instant時輸出的時間比預(yù)期少了八個小時的問題解決,感興趣的可以了解一下2024-09-09
詳解java.lang.reflect.Modifier.isInterface()方法
這篇文章主要介紹了詳解java.lang.reflect.Modifier.isInterface()方法的相關(guān)資料,這里提供實例幫助大家理解這個方法的使用,需要的朋友可以參考下2017-09-09
springboot實現(xiàn)執(zhí)行sql語句打印到控制臺
這篇文章主要介紹了springboot實現(xiàn)執(zhí)行sql語句打印到控制臺的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
Springboot項目中實現(xiàn)微信小程序登錄案例(最新推薦)
文章介紹了如何通過微信開放平臺的授權(quán)登錄功能實現(xiàn)Spring Boot項目與微信小程序的微信登錄,本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友一起看看吧2025-02-02
IntelliJ IDEA 2020.3 重大特性(新功能一覽)
這篇文章主要介紹了IntelliJ IDEA 2020.3 重大特性(新功能一覽),本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12

