Spring Cache 是作用在方法上的,其核心思想是,当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存在缓存中。每次调用需要缓存功能的方法时,Spring 会检查指定参数的指定目标方法是否已经被调用过,如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。
本文只针对如何使用缓存来完成业务上的需求。如果需要具体学习的小伙伴可以移步到https://wenku.baidu.com/view/21c09439ff4ffe4733687e21af45b307e871f980.html(好文推荐)
@Cacheable可以标记在⼀个⽅法上,也可以标记在⼀个类上。当标记在⼀个⽅法上时表⽰该⽅法是⽀持缓存的,当标记在⼀个类上时,则表⽰该类所有的⽅法都是⽀持缓存的。
@SpringBootApplication
@EnableCaching
public class DfsApplication {
public static void main(String[] args) {
SpringApplication.run(DfsApplication.class, args);
}
}
<!--Redis缓存-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
/**
* 生产大屏当天状态总览
*
* @return
*/
@Cacheable(cacheNames = "dfs_screen_information", key = "'lineId=' + #lineId + ',componentName=' + #componentName + ',dateIn=' + #dateIn")
@GetMapping("/information")
public ResponseData workOrderInformation(@RequestParam(value = "componentName", required = false) String componentName,
@RequestParam(value = "date", required = false) String dateIn,
@RequestParam(value = "lineId", required = false) Integer lineId) {
Date date = DateUtil.parse(dateIn, DateUtil.DATETIME_FORMAT);
return ResponseData.success(productionService.workOrderInformation(lineId, date));
}
/**
* redis配置类
*
* @author shuang
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
/**
* redis缓存管理器
*/
@Bean
public CacheManager screenCacheManager(RedisTemplate<String, Object> template) {
return RedisCacheManager.RedisCacheManagerBuilder
//Redis链接工厂
.fromConnectionFactory(Objects.requireNonNull(template.getConnectionFactory()))
// 默认缓存 过期时间配置1h
//.cacheDefaults(getCacheConfigurationWithTtl(60 * 60))
// 生产大屏缓存 过期时间
.withCacheConfiguration("dfs_screen_information", getCacheConfigurationWithTtl(5))
.withCacheConfiguration("dfs_screen_work_order_list", getCacheConfigurationWithTtl(5))
.withCacheConfiguration("dfs_screen_plan_rate", getCacheConfigurationWithTtl(5))
//配置同步修改或删除put/evict(事务感知)
.transactionAware()
.build();
}
/**
* 缓存配置
* @param seconds 过期时间 s
* @return
*/
private RedisCacheConfiguration getCacheConfigurationWithTtl(long seconds) {
return RedisCacheConfiguration
.defaultCacheConfig()
// 不缓存null值
.disableCachingNullValues()
// 缓存数据保存时间设置
.entryTtl(Duration.ofSeconds(seconds));
}
}
● cacheNames/value :用来指定缓存组件的名字
● key :缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 spEL 表达式来编写)
● keyGenerator :key 的生成器。 key 和 keyGenerator 二选一使用
● cacheManager :可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。
● condition :可以用来指定符合条件的情况下才缓存
● unless :否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过 #result 获取方法结果)
● sync :是否使用异步模式。
注解使用示例:
/**
* 生产大屏生产计划与进度
*
* @return
*/
@Cacheable(cacheNames = "dfs_screen_work_order_list", key = "#lineId", condition = "#componentName = 'test'")
@GetMapping("/workOrder/list")
public ResponseData workOrderList(@RequestParam(value = "componentName", required = false) String componentName,
@RequestParam(value = "date", required = false) String dateIn,
@RequestParam(value = "lineId", required = false) Integer lineId) {
Date date = DateUtil.parse(dateIn, DateUtil.DATETIME_FORMAT);
return ResponseData.success(productionService.listWorkOrder(date));
}