springboot集成springcache
Spring Boot 集成 Spring Cache 后,可以快速实现缓存读写能力。查询时优先读取缓存,新增、修改和删除操作则可以在更新数据库的同时维护缓存状态。
一、包依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>二、配置文件
spring:
cache:
#指定缓存类型为redis
type: redis三、配置信息加载
需要先开启 @EnableCaching 注解。
下面示例中定义了两个 RedisCacheManager,分别用于配置不同的缓存过期时间,同时统一了序列化方式,默认使用 JSON。
@Configuration
@EnableCaching
public class RedisConfig {
/**
* 自定义spring cache缓存key规则
* @return org.springframework.cache.interceptor.KeyGenerator
* @author lcy
* @date 2021/6/29 14:17
**/
@Bean
public KeyGenerator keyGenerator(){
return (Object target,Method method,Object... params) ->
{
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
};
}
/**
* 默认spring cache配置 过期时间一个小时
* @param connectionFactory 连接工厂
* @return org.springframework.data.redis.cache.RedisCacheManager
* @author lcy
* @date 2021/6/29 14:14
**/
@Bean
@Primary
public RedisCacheManager cacheManager1Hour(RedisConnectionFactory connectionFactory){
RedisCacheConfiguration config = instanceConfig(3600L);
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.transactionAware()
.build();
}
/**
* spring cache配置 过期时间一天
* @param connectionFactory 连接工厂
* @return org.springframework.data.redis.cache.RedisCacheManager
* @author lcy
* @date 2021/6/29 14:14
**/
@Bean
public RedisCacheManager cacheManager1Day(RedisConnectionFactory connectionFactory){
RedisCacheConfiguration config = instanceConfig(3600 * 24L);
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.transactionAware()
.build();
}
/**
* spring cache的过期时间配置
* @param ttl 过期时间,以秒为单位
* @return org.springframework.data.redis.cache.RedisCacheConfiguration
* @author lcy
* @date 2021/6/29 14:13
**/
private RedisCacheConfiguration instanceConfig(Long ttl){
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
jackson2JsonRedisSerializer.setObjectMapper(serializingObjectMapper());
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(ttl))
.disableCachingNullValues()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
}
/**
* 获取序列化的jackson对象
* @return com.fasterxml.jackson.databind.ObjectMapper
* @author lcy
* @date 2021/6/29 14:12
**/
public ObjectMapper serializingObjectMapper(){
//创建jsr310包下的javaTimeModule对象,其中包含了jdk8以后的时间类型序列化和反序列化配置
JavaTimeModule javaTimeModule = new JavaTimeModule();
//LocalDateTime序列化设置为yyyy-MM-dd HH:mm:ss
LocalDateTimeSerializer localDateTimeSerializer =
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
//增加序列化到配置当中
javaTimeModule.addSerializer(LocalDateTime.class,localDateTimeSerializer);
//LocalDateTime反序列化设置为yyyy-MM-dd HH:mm:ss
LocalDateTimeDeserializer localDateTimeDeserializer =
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
//增加反序列化到配置当中
javaTimeModule.addDeserializer(LocalDateTime.class,localDateTimeDeserializer);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
//注册配置--jdk8类型
objectMapper.registerModule(javaTimeModule);
// 去掉各种@JsonSerialize注解的解析
objectMapper.configure(MapperFeature.USE_ANNOTATIONS,false);
// 只针对非空的值进行序列化
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 将类型序列化到属性json字符串中
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.PROPERTY);
objectMapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
return objectMapper;
}
}四、注解使用和介绍
注解支持两种使用方式:
类注解:类上使用
@CacheConfig(cacheNames="xxx")。在同一个 Redis 实例中,cacheNames建议保持明确且唯一,避免多个类共用默认值带来冲突方法注解:直接在方法上声明缓存行为,这种方式更常见,也更易于按业务粒度控制
下面是常见注解属性的说明,这些属性在多个缓存注解中都可以使用。
value:缓存名称,可以配置多个key:缓存 Key 规则,可以使用 Spring EL 表达式;如果未设置keyGenerator,默认使用方法参数组合生成 Keycondition:缓存条件,可以使用 Spring EL,返回true时才会进入缓存keyGenerator:不配置时使用默认的 Key 生成器;如果显式指定,则填写对应 Bean 名称cacheManager:不配置时使用默认的缓存管理器;如果显式指定,则填写对应 Bean 名称
例如:
//根据方法名称使用key,这里会出现不同的用户参数也会获取到相同的结果
@Cacheable(value = {"redis"}, key="#root.methodName")
//根据参数对象的id添加数据
@Cacheable(value = {"redis"}, key="#param.id")
//如果入参不是对象,根据入参的参数数组添加数据
@Cacheable(value = {"redis"}, key="#root.args[0]")
//分页获取数据
@Cacheable(value = {"product_page"},key="#root.methodName + #page+'_'+#size")下面是常见方法注解的说明。
4.1 @Cacheable
如果缓存中已存在结果,则直接返回缓存值;如果缓存中不存在,则执行方法并将结果写入缓存。
这个注解中有一个比较常用的属性可以辅助防止缓存击穿:
- sync:将缓存锁住,只有一个线程可以进入计算,而阻塞其它线程,直到返回结果更新到缓存当中。true为开启,默认不开启
4.2 @CachePut
在修改数据时同步更新缓存,可以使用 @CachePut。该注解会始终执行目标方法,并将执行结果写入缓存。
4.3 @CacheEvict
在删除数据时同步清理缓存,适合移除陈旧数据或不再使用的数据。
这里有一个属性需要特别注意:
beforeInvocation = false
缓存的清除是否在方法之前执行 ,默认代表缓存清除操作是在方法执行之后执行;
如果出现异常缓存就不会清除
beforeInvocation = true
- 代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除
4.4 @Caching
组合注解,适合在同一个方法中同时操作多个缓存 Key 的场景。
例如:
@Caching(
cacheable = {
@Cacheable(value = "redis",keyGenerator = "keyGenerator")
},
put = {
@CachePut(value = "redis",key = "#id"),
@CachePut(value = "redis",key = "'redis:'+#id")
}
)五、使用redis session共享外部session
通过session实现登录态的控制的时候可以使用
5.1 依赖
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>5.2 配置文件
maxInactiveIntervalInSeconds: 设置 Session 失效时间,使用 Redis Session 之后,原 Spring Boot 的 server.session.timeout 属性不再生效。
