简介:java系列技术分享(持续更新中…)
初衷:一起学习、一起进步、坚持不懈
如果文章内容有误与您的想法不一致,欢迎大家在评论区指正
希望这篇文章对你有所帮助,欢迎点赞 收藏 ⭐留言更多文章请点击
官方文档中有详细介绍:https://docs.spring.io/spring-framework/reference/integration/cache/annotations.html
Spring cache
是Spring提供的通用缓存框架,利用AOP,实现了基于注解的缓存功能。
Spring cache
只是提供了一层抽象,地城可以切换不同的cache实现,具体就是通过CacheManager接口开统一不同的缓存技术,CacheManager
是Spring
提供的各种缓存技术抽象接口。
注解 | 描述 |
---|---|
@EnableCaching |
开启缓存注解功能 |
@Cacheable |
从缓存查询,存在则返回,不存在查询数据库,存入缓存 |
@CachePut |
将数据结果存入缓存 |
@CacheEvict |
清空缓存内容属性(allEntries = true) 表示清空所有 |
@Caching |
多缓存配置 |
缓存非null值
因为在使用中,可能会查询到null所以进行处理
在@Cacheable注解中,提供了两个属性,分别是 :condition
,unless
@Cacheable(value = "cache",key = "#id",unless = "#result == null")
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
return providerService.queryById(id);
}
注意: 这里只能使用unless,因为在condition中无法获取到结果#result
@EnableCaching
开启缓存支持。Spring cache
的基本功能是spring核心(spring-context)
中提供,无需引入其他依赖。ConcurrentHashMap
作为本地缓存存储数据,如何要使用其他的缓存框架,我们只需要做简单的配置即可。Spring data Redis
的maven坐标即可 <dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
@EnableCaching
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
默认情况下,Spring cache使用ConcurrentHashMap
作为本地缓存存储数据,如何要使用其他的缓存框架,我们只需要做简单的配置即可。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
spring:
redis:
host: 196.120.168.100
port: 6379
database: 1
password:
下面方法只是根据id查询数据库,因此简单的代码就不展示了,我们主要关注注解的使用就可以了。
/**
* 根据id查询用户信息
*/
@Cacheable("user")
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
return providerService.queryById(id);
}
spring:
cache:
type: redis
但是发现redis存储的格式是二进制形式(默认序列化使用的是 JdkSerializationRedisSerializer
,存储二进制字节码)。不够直观,这时我们可以自定义RedisTemplate
模板
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer); // key
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// 指定要序列化的域(field,get,set),访问修饰符(public,private,protected)
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); //value
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
RedisTemplate调用是正常的
,而只有使用@Cacheable("user")
时是二进制默认缓存的值是二进制的
,这时添加如下配置,定义redisCacheManager
与redisTemplate
配置进行绑定 @Bean
public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
// .entryTtl(Duration.ofHours(1))// 设置缓存有效期一小时
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
value
:缓存的名称,每个缓存名称下面可以有多个keykey
: 缓存的key, 支持SPEL表达式
/**
* 根据id查询用户信息
*/
@CachePut(value = "user",key = "#result.id")
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
return providerService.queryById(id);
}
官方文档中有详细介绍:https://docs.spring.io/spring-framework/reference/integration/cache/annotations.html
这里列出一些,供参考
常用格式
@CachePut(value = "cache",key = "#user.id")
@CachePut(value = "cache",key = "#p0.id")
@CachePut(value = "cache",key = "#root.args[0].id")
@CachePut(value = "cache",key = "#id")
@CachePut(value = "cache",key = "'test'+ #id")
静态方法调用
@Cacheable(value = "user",key = "T(com.use.dto.bean.CurrentRequest).getUser().getUid()")
例如:
@CachePut
中可以
使用#result
@Cacheable
中则不可以
使用,具体这里不一一测试,使用时还需注意
在真实开发中失效时间是必须设置的,不然一直占用内存是不可取的
全局生效
spring:
redis:
time-to-live: 1800000 # 缓存过期时间 单位毫秒
局部设置
@Configuration
public class RedisCacheConfig {
//设置失效时间
private static final Map<String, Duration> cacheMap;
static {
cacheMap = ImmutableMap.<String, Duration>builder().put("user", Duration.ofMinutes(5)).build();
}
//配置RedisCacheManagerBuilderCustomizer对象
@Bean
public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
return (builder) -> {
//根据不同的cachename设置不同的失效时间
for (Map.Entry<String, Duration> entry : cacheMap.entrySet()) {
builder.withCacheConfiguration(entry.getKey(),
RedisCacheConfiguration.defaultCacheConfig().entryTtl(entry.getValue()));
}
};
}
}