目錄
為什么使用Spring Cache
如何使用Spring Cache
1 加依賴
2 開啟緩存
3 加緩存注解
序列化以及過期時間等問題
解決方案:自定義序列化方式
1.自定義序列化方式并設(shè)置白名單
2.配置并設(shè)置緩存的過期時間
為什么使用Spring Cache
????????緩存有諸多的好處,于是大家就摩拳擦掌準(zhǔn)備給自己的應(yīng)用加上緩存的功能。但是網(wǎng)上一搜卻發(fā)現(xiàn)緩存的框架太多了,各有各的優(yōu)勢,比如Redis、Memcached、Guava、Caffeine等等。
????????如果我們的程序想要使用緩存,就要與這些框架耦合。聰明的架構(gòu)師已經(jīng)在利用接口來降低耦合了,利用面向?qū)ο蟮某橄蠛投鄳B(tài)的特性,做到業(yè)務(wù)代碼與具體的框架分離。
但我們?nèi)匀恍枰@式地在代碼中去調(diào)用與緩存有關(guān)的接口和方法,在合適的時候插入數(shù)據(jù)到緩存里,在合適的時候從緩存中讀取數(shù)據(jù)。
????????想一想AOP的適用場景,這不就是天生就應(yīng)該AOP去做的嗎?
????????是的,Spring Cache就是一個這個框架。它利用了AOP,實現(xiàn)了基于注解的緩存功能,并且進(jìn)行了合理的抽象,業(yè)務(wù)代碼不用關(guān)心底層是使用了什么緩存框架,只需要簡單地加一個注解,就能實現(xiàn)緩存功能了。而且Spring Cache也提供了很多默認(rèn)的配置,用戶可以3秒鐘就使用上一個很不錯的緩存功能。
如何使用Spring Cache
????????上面的3秒鐘,絕對不夸張。使用SpringCache分為很簡單的三步:加依賴,開啟緩存,加緩存注解。
1 加依賴
<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>
<!--json依賴-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
2 開啟緩存
在啟動類加上@EnableCaching
注解即可開啟使用緩存。
@Slf4j
@SpringBootApplication
@EnableCaching
public class WaiMaiApplication {
public static void main(String[] args) {
SpringApplication.run(WaiMaiApplication.class,args);
log.info("項目啟動成功!123");
}
}
3 加緩存注解
spring boot cache 提供了一些注解方便做cache應(yīng)用。
(1)@CacheConfig:主要用于配置該類中會用到的一些共用的緩存配置
(2)@Cacheable:主要方法返回值加入緩存。同時在查詢時,會先從緩存中取,若不存在才再發(fā)起對數(shù)據(jù)庫的訪問。
(3)@CachePut:配置于函數(shù)上,能夠根據(jù)參數(shù)定義條件進(jìn)行緩存,與@Cacheable不同的是,每次回真實調(diào)用函數(shù),所以主要用于數(shù)據(jù)新增和修改操作上。
(4)@CacheEvict:配置于函數(shù)上,通常用在刪除方法上,用來從緩存中移除對應(yīng)數(shù)據(jù)
(5)@Caching:配置于函數(shù)上,組合多個Cache注解使用。
例子:
/**
* 根據(jù)條件查詢套餐數(shù)據(jù) 在查詢到數(shù)據(jù)的同時向redis添加緩存
* @param setmeal
* @return
*/
@GetMapping("/list")
@Cacheable(cacheNames= "setmealCache",key = "#setmeal.categoryId+'_'+#setmeal.status" )
public R<List<Setmeal>> list(Setmeal setmeal){
LambdaQueryWrapper<Setmeal> queryWrapper=new LambdaQueryWrapper<>();
queryWrapper.eq(setmeal.getCategoryId()!=null,Setmeal::getCategoryId,setmeal.getCategoryId())
.eq(setmeal.getStatus()!=null,Setmeal::getStatus,setmeal.getStatus())
.orderByDesc(Setmeal::getUpdateTime);
List<Setmeal> setmealList = setmealService.list(queryWrapper);
return R.success(setmealList);
}
/**
* 刪除套餐 更改數(shù)據(jù)庫數(shù)據(jù)后同時刪除緩存
* @param ids
* @return
*/
@DeleteMapping
@CacheEvict(value = "setmealCache",allEntries = true)
public R<String> delete(Long[] ids){
log.info("ids:{}",ids);
setmealService.removeWithDish(ids);
return R.success("套餐數(shù)據(jù)刪除成功!");
}
序列化以及過期時間等問題
在設(shè)置緩存注解后,添加到Redis的緩存數(shù)據(jù)是用StringRedisSerializer和JdkSerializationRedisSerialize為序列話策略,JdkSerializationRedisSerialize非常好,但是其序列化的結(jié)果是一堆子節(jié)碼,這給我們閱讀帶來了麻煩。
解決方案:自定義序列化方式
我們這里自定義了FastJsonRedisSerializer 序列化對象后緩存到redis,可以更 方便的觀察緩存數(shù)據(jù)。文章來源:http://www.zghlxwxcb.cn/news/detail-605793.html
1.自定義序列化方式并設(shè)置白名單
package com.songqiao.waimai.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.nio.charset.Charset;
/**
* 說明:自定義redis序列化方式
*
* @author Songqiao
* @version V1.0
* @since 2023.07.24
*/
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
//添加白名單 防止反序列化錯誤 反序列化報錯 com.alibaba.fastjson.JSONException: autoType is not support
static {
ParserConfig.getGlobalInstance().addAccept("com.songqiao.waimai");
}
public FastJsonRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz);
}
}
2.配置并設(shè)置緩存的過期時間
package com.songqiao.waimai.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
/**
*
* @author Songqiao
* @version V1.0
* @since 2023.07.24
*/
@Configuration
@EnableCaching
public class MyCacheConfig extends CachingConfigurerSupport {
/**
* 設(shè)置 redis 數(shù)據(jù)默認(rèn)過期時間
* 設(shè)置@cacheable 序列化方式
* @return
*/
@Bean
public RedisCacheConfiguration redisCacheConfiguration(){
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofDays(30));
return configuration;
}
}
注解方式實現(xiàn)緩存、以及序列化等相關(guān)問題已解決!文章來源地址http://www.zghlxwxcb.cn/news/detail-605793.html
到了這里,關(guān)于SpringCache 框架使用以及序列化和緩存過期時間問題的解決的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!