緩存通常用來加快資料庫中經常要使用的資料。大部分情況下我們使用 redis 來緩存 MySQL 資料庫的熱點資料。
啟用緩存#
在 spring boot 中使用緩存還是比較簡單的
首先添加依賴
<!-- cache 依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
在啟動類開啟緩存支持
@SpringBootApplication
@EnableCaching
在配置文件中指定使用 redis 緩存,如果不指定則使用 jvm 內存
在使用 redis 做緩存之前,需要正確的配置 redis 的連接信息
#cacheing
spring.cache.type=redis
#指定前綴
#spring.cache.redis.key-prefix=test
#指定存活時長
#spring.cache.redis.time-to-live= 1d
最後在 redis 的配置類中增加 @EnableCaching
註解和 緩存管理器
/**
* 申明緩存管理器,會創建一個切面(aspect)並觸發Spring緩存註解的切點(pointcut)
* 根據類或者方法所使用的註解以及緩存的狀態,這個切面會從緩存中獲取資料,將資料添加到緩存之中或者從緩存中移除某個值
*
* @return
*/
@Bean
@SuppressWarnings("all")
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解決查詢緩存轉換異常的問題
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解決亂碼的問題)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(1))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
緩存註解#
緩存註解 | 解釋 |
---|---|
@EnableCaching | 開啟緩存註解的支持 |
@CacheConfig | 用於統一制定一些配置參數,這樣在其他緩存註解裡面就不用重複指定 |
@Cacheable | 如果之前已經有緩存資料值直接返回緩存資料,否則執行方法,緩存方法的返回結果 |
@CachePut | 能夠根據方法的請求參數對其結果進行緩存,和 @Cacheable 不同的是,它每次都會觸發真實方法的調用 |
@CacheEvict | 能夠根據一定的條件對緩存進行清空 |
@Caching | 組合多個 Cache 註解的使用 |
@CacheConfig#
此註解常用來配置統一的緩存參數
// 在controller中使用此註解用來指定緩存的名字,類似於前綴
@CacheConfig(cacheNames = "test")
@Cacheable#
此註解常用於查詢方法中,使用此註解後會先從緩存中查,如果緩存中沒有,再從資料庫中查,並把查詢出的結果放入緩存中。
Mermaid Loading...
// 如果配置了@CacheConfig的全局cacheName/value 則這裡面的可以省略
@Cacheable(value = "test", key = "methodName")
// @Cacheable支持el表達式
@Cacheable(key = "methodName + ':' + #p0 + ':' + #p1")
public Result<Object> getSubordinateAddress(String province,String city){}
@Cacheable(value="users", key="#user.id")
public User find(User user) {}
key
支持的屬性列表如下
屬性名稱 | 描述 | 示例 |
---|---|---|
methodName | 當前方法名 | #root.methodName |
method | 當前方法 | #root.method.name |
target | 當前被調用的對象 | #root.target |
targetClass | 當前被調用的對象的 class | #root.targetClass |
args | 當前方法參數組成的數組 | #root.args[0] |
caches | 當前被調用的方法使用的 Cache | #root.caches[0].name |
@CachePut#
此註解常用來更新緩存。它會忽略緩存中的值,而是始終執行方法。
執行順序為 調用方法 ---> 獲取結果 ---> 更新緩存
Mermaid Loading...
@CachePut(value = "myCache", key = "#entity.id")
public void saveEntity(MyEntity entity) {
repository.save(entity);
}
@CacheEvict#
此註解用來刪除對應的緩存。
@CacheEvict(value = "myCache", key = "#id")
public void deleteEntityById(Long id) {
repository.deleteById(id);
}
在使用 allEntries=true
時,會忽略 key,刪除指定 cacheName/value 中的全部值。
你也可以使用 cacheMange 對象來刪除指定的緩存,以下代碼表示當 test 緩存不為空時,將其清空
Objects.requireNonNull(restTemplateConfig.cacheManager(null).getCache("test")).clear();
@Caching#
此註解用來組合多個上面的緩存註解進行使用
@Caching(
cacheable = {
@Cacheable(value = "myCache", key = "#id")
},
evict = {
@CacheEvict(value = "otherCache", key = "#id")
}
)
public MyEntity getEntityById(Long id) {
return repository.findById(id).orElse(null);
}
調用順序如下
Mermaid Loading...
SpringBoot 專案中使用緩存 Cache 的正確姿勢!!!
SpringBoot 緩存管理 @EnableCaching、@Cacheable