赞
踩
<!--springCache依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--springCache使用redis依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring:
cache:
type: redis #配置reids作为缓存
redis:
time-to-live: 60000 #缓存过期时间为60秒,单位毫秒
key-prefix: HEIZI_ #key增加前缀
use-key-prefix: true #是否开启前缀(Ⅰ.如果为true,并且key-prefix指定了值,那么缓存的key就是:HEIZI_key。Ⅱ.如果为true,key-prefix没有指定前缀,那么缓存的key就是:缓存的名字::key。Ⅲ.如果为false,缓存的key就是:key)
cache-null-values: true #是否缓存空值,防止缓存穿透问题
#在启动类加上此注解
@EnableCaching
@Cacheable
:保存到缓存中。
@CacheEvict
:删除缓存。
@CachePut
:不影响方法执行,更新缓存。(双写模式默认)
@Caching
:多条命令操作。
@CacheConfig
:共享缓存配置(类级别)。
# 把结果放到缓存,如果有缓存,那么不调用接口,直接返回缓存里面的数据。没有缓存,调用接口返回数据,并且把结果存到缓存中去。缓存的value存放的是jdk序列化的内容。 # 缓存的名称:ikun,一个缓存下可以有多个key,key的名称:ceshi(支持Spring的表达式语言SPEL语法) @Cacheable(value = {"ikun"},key = "'ceshi'") Object detail(@PathVariable("id") Serializable id); # 缓存的名称:ikun,一个缓存下可以有多个key,key的名称:结果的id值 @Cacheable(value = {"ikun"},key = "#result.id") Object detail(@PathVariable("id") Serializable id); # 缓存的名称:ikun,一个缓存下可以有多个key,key的名称:参数的id值 @Cacheable(value = {"ikun"},key = "#heizi.id") Object detail(HeiZi heizi); //删除ikun缓存下的,key为ceshi的缓存。 @CacheEvict(value = {"ikun"},key = "'ceshi'") String update(HeiZi heizi); //删除ikun缓存下的,所有的缓存。 @CacheEvict(value = {"ikun"},allEntries = true) String update(HeiZi heizi); //删除ikun缓存下的,key为ceshi1和ceshi2的缓存。 @Caching( evict = { @CacheEvict(value = "ikun",key = "'ceshi1'"), @CacheEvict(value = "ikun",key = "'ceshi2'") } ) String update(HeiZi heizi);
SpEl表达式
名称 | 位置 | 描述 | 实例 |
---|---|---|---|
methodName | root对象 | 当前被调用的方法名 | #root.methodname |
method | root对象 | 当前被调用的方法 | #root.method.name |
target | root对象 | 当前被调用的目标对象实例 | #root.target |
targetClass | root对象 | 当前被调用的目标对象的类 | #root.targetClass |
args | root对象 | 当前被调用的方法的参数列表 | #root.args[0] |
caches | root对象 | 当前方法调用使用的缓存列表 | #root.caches[0].name |
Argument Name | 执行上下文 | 当前被调用的方法的参数,如detail(HeiZi heizi),可以通过#heizi.id获得参数 | #heizi.id |
result | 执行上下文 | 方法执行后的返回值(仅当方法执行后的判断有效) | #result.id |
因为默认缓存,存的是JDK序列化的内容,如果我们要想存JSON怎么办呢?
@Configuration @EnableCaching @EnableConfigurationProperties({CacheProperties.class}) public class MyRedisConfig { @Bean RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){ RedisCacheConfiguration redisConfig = RedisCacheConfiguration.defaultCacheConfig(); //设置redis存的格式为JSON //使用GenericJackson2JsonRedisSerializer()和StringRedisSerializer()都可以 redisConfig = redisConfig.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())); redisConfig = redisConfig.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); //使你配置文件的配置生效 CacheProperties.Redis redisProperties = cacheProperties.getRedis(); //读取配置文件的缓存过期时间 if (redisProperties.getTimeToLive() != null) { redisConfig = redisConfig.entryTtl(redisProperties.getTimeToLive()); } //读取配置文件的缓存的前缀 if (redisProperties.getKeyPrefix() != null) { redisConfig = redisConfig.prefixCacheNameWith(redisProperties.getKeyPrefix()); } //读取配置文件的缓存是否存空值 if (!redisProperties.isCacheNullValues()) { redisConfig = redisConfig.disableCachingNullValues(); } //读取配置文件的是否开启缓存前缀 if (!redisProperties.isUseKeyPrefix()) { redisConfig = redisConfig.disableKeyPrefix(); } return redisConfig; } }
缓存穿透: 查询为null的数据。解决: 设置缓存是否为空。(cache-null-values: true)。
缓存击穿: 大量并发查询过期的缓存。解决: 加锁 @Cacheable(sync = true)。
缓存雪崩: 大量缓存同时过期。解决: 加随机时间 (time-to-live: 60000)。
springCache并没有对写模式进行特别的配置和处理,要根据不同的场景进行不同的操作。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。