在Spring Boot中对于缓存的支持,提供了一系列的自动化配置,使我们可以非常方便的使用缓存。
Hello Cache
spring boot为我们提供了开箱即用的缓存功能。只需要引入缓存包,并配置相应注解即可。默认使用ConcurrentMapCacheManager内存缓存。
1. 在pom.xml中引入cache依赖,添加如下内容:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2. 在有@Configuration注解的类中增加@EnableCaching注解开启缓存功能
@Configuration
@EnableCaching
public class CachingConfig {}
3. 在数据访问类中,增加缓存配置注解,如:
@Cacheable("dupulicateString")
public String dupulicate(String s){
return s+s;
}
Spring Cache基本注解
- @Cacheable 根据方法的请求参数对其结果进行缓存,建议尽量使用本方法。
- @CachePut 根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是它每次都会触发真实方法的调用
- @CachEvict 根据一定的条件对缓存进行清空
- @CacheConfig 指定全局Cache配置。Spring 4.1之前需要每个方法上都指定,Spring 4.1时可以直接在类级别使用@CacheConfig指定。
@Cacheable注解主要参数,所有参数都是非必须参数:
- value、cacheNames:用于指定缓存存储的集合名。如果类上没有配置@CacheConfig,则为必须配置的参数。
- key:缓存对象key值,缺省按照函数的所有参数组合作为key值,支持SpEL表达式
- condition:缓存对象的条件,只有满足表达式条件的内容才会被缓存,支持SpEL表达式
- unless:缓存对象的条件,在函数被调用之后才做判断的,可以对result进行判断。
- keyGenerator:用于指定key生成器,非必需,该参数与key是互斥的。
- cacheManager:用于指定使用哪个缓存管理器
- cacheResolver:用于指定使用那个缓存解析器
spring cache提供的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 | 当前方法调用使用的缓存列表(如@Cacheable(value={“cache1”, “cache2”})),则有两个cache |
argument name | 执行上下文 | user.id | 当前被调用的方法的参数,如findById(Long id),我们可以通过#id拿到参数 |
result | 执行上下文 | result | 方法执行后的返回值(仅当方法执行之后的判断有效,如‘unless’,’cache evict’的beforeInvocation=false) |
使用redis做缓存
spring boot中使用redis做缓存只需要引入redis包即可。CacheAutoConfiguration会根据优先级自动替换掉默认的ConcurrentMapCacheManager内存缓存。
1. 在pom.xml中引入cache依赖,添加如下内容:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. 配置RedisTemplate
RedisTemplate默认的序列化在终端查看redis数据时不方便阅读,建议调整为容易阅读的序列化方案。
@Bean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(JedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
Object.class);
ObjectMapper objectMapper = new ObjectMapper();
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
template.setDefaultSerializer(jackson2JsonRedisSerializer);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer);
template.afterPropertiesSet();
return template;
}
3. 添加超时时间
redis缓存默认永久有效,需要根据缓存名称设置超时时间。
@Bean
public CacheManagerCustomizer<RedisCacheManager> customizer(){
return new CacheManagerCustomizer<RedisCacheManager>(){
@Override
public void customize(RedisCacheManager cacheManager) {
//设置缓存过期时间
Map<String, Long> expires=new HashMap<>();
expires.put("wrapMap", 1000L);
cacheManager.setExpires(expires);
}
};
}
混合使用不同的缓存
Spring Cache整个应用中默认只使用一种类型的缓存。但在使用了redis做缓存的情况下,我们依然需要将一些小数据放到内存里。从而提高性能并保证只有系统重启时才刷新数据。这时我们需要使用CompositeCacheManager做组合缓存。
1. 配置不同的缓存,并声明使用的缓存类型。
@Configuration
public class CompositeCacheConfig{
@Bean(name = "simpleCacheManager")
public ConcurrentMapCacheManager simpleCacheManager() {
return new ConcurrentMapCacheManager();
}
@Bean(name = "redisCacheManager")
public RedisCacheManager redisCacheManager(CacheManagerCustomizer<RedisCacheManager> customizer,
RedisTemplate<Object, Object> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setUsePrefix(true);
customizer.customize(cacheManager);
return cacheManager;
}
@Bean
public CompositeCacheManager cacheManager(ConcurrentMapCacheManager simpleCacheManager,RedisCacheManager redisCacheManager) {
CompositeCacheManager cacheManager = new CompositeCacheManager();
cacheManager.setFallbackToNoOpCache(false);
List<CacheManager> cacheManagers = Lists.newArrayList();
cacheManagers.add(simpleCacheManager);//顺序决定默认管理器
cacheManagers.add(redisCacheManager);
cacheManager.setCacheManagers(cacheManagers);
return cacheManager;
}
}
2. 实现CachingConfigurer
@Configuration
public class CompositeCachingConfigurer implements CachingConfigurer {
@Autowired(required = false)
private CompositeCacheManager cacheManager;
@Override
public CacheManager cacheManager() {
return cacheManager;
}
@Bean
@Override
public CacheResolver cacheResolver() {
return new SimpleCacheResolver(cacheManager);
}
@Override
public KeyGenerator keyGenerator() {
return new SimpleKeyGenerator();
}
@Override
public CacheErrorHandler errorHandler() {
return null;
}
}
在方法中指定CacheManager
@Cacheable(value="wrapMap",cacheManager="simpleCacheManager")
public Map<String,String> wrap(String s)
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html
http://jinnianshilongnian.iteye.com/blog/2001040