Spring Boot - Spring Cache
- 缓存
- 服务器自身(内存)的缓存
- 利用java程序中的变量
- 简单
- 集群环境中多个实例无法共享同步
- 利用java程序中的变量
- 缓存服务器(一般支持集群、分布式)
- Redis
- Memcached
- 服务器自身(内存)的缓存
- Spring中使用注解使用缓存
- 启动类或者配置类
- 使用@EnableCaching,必须使用,否则后续注解虽然不报错,但没有使用缓存
- 可以放一个@Bean,用来注入CacheManager
- 启动类或者配置类
@EnableCaching
@EnableScheduling
@Configuration
public class CacheConfig {
@Bean
@Primary
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("assets");
}
}
* 使用注解标识方法()
* @Cacheable,通常用在get方法上
* @CachePut:运行后会更新/新建缓存中的值,通常用在update方法上
* @CacheEvict:运行后会删掉缓存中的值,通常用在delete方法上
* 使用注解标识类(方法上就不用标识了)
* @CacheConfig:相当于该类下所有的方法的cacheNames都是其中指定的字符串?
* 参数
* 标识缓存项,都是用注解中的cacheNames参数和key参数组合起来的:**缓存的key是cacheNames::key**
* cacheNames可以是一个字符串数组,可以对应多个缓存的key,每个方法都需要指定cacheNames参数
* key
* 通常用SpringEL表达式。
* 以\#开头,内部以.进行分级分隔。
* **默认按照方法的参数自动生成**
* 可以通过keyGenerator参数自定义生成方式
* 有时key可以省略,key有默认的机制。如果方法只有一个参数,那么就会用cacheNames和参数值组合成key;如果有多个参数的时候,就会把多个参数组合起来再组合成key。**所有要看情况,key有时可以省略,有时不可以。**
* condition可以指定一个条件,用于执行方法前判断是否使用注解的功能
* unless用于执行方法后,用返回值?判断是否使用注解提供的功能
* cacheManager、CacheResolver、keyGenerator
* @CacheEvict多了两个参数
* allEntries:值为true则不管key,清除cacheName下所有key的缓存
* beforeInvocation:值为true,执行方法前清除,默认是执行方法后清除
* 设置缓存过期
* 可以和Scheduled Tasks结合,使用CacheEvict注解定时清除缓存
* 某些缓存服务如Redis,可以通过application.yml配置一个全局的过期时间(默认不过期)
- 使用Redis
- 在maven或者gradle中加入依赖
- 在application.yml中加入配置
- 可以通过使用RedisTemplate(RabbitMQ中有类似的概念用来发数据到队列)单独设置一些过期时间等
- 有可能的坑
- application.yml中其实可以配置key前缀、是否使用key前缀。如果打开了这两个开关,那么有可能导致代码中的cacheNames参数失效,如果两个方法的key相同,那么会导致缓存的key相同导致混乱。根本原因是spring把cacheNames参数也当成了application.yml中所谓的key,所以这两个参数一般不要配。
- 使用
- 需要在build.gradle中添加依赖:compile('org.springframework.boot:spring-boot-starter-data-redis'),然后就可以使用RedisTemplate<String, XXX>类了
- application.properties文件中的配置
- 配置类(其实这一个就够了)
- 注入生成的redisSetRepository可以直接用来进行redis操作,比如redisRepository.put
@Configuration
public class RedisConfig {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Value("${oee.cache.ttl.hours:24}")
private long timeout;
@Bean
public RedisRepository redisRepository()
{
return new RedisRepository(cacheEntryRedisTemplate(), timeout, TimeUnit.HOURS);
}
@Bean
public RedisSetRepository redisSetRepository()
{
return new RedisSetRepository(stringRedisTemplate());
}
private RedisTemplate<String, CacheEntry> cacheEntryRedisTemplate()
{
StringRedisSerializer stringSerializer = new StringRedisSerializer(StandardCharsets.UTF_8);
Jackson2JsonRedisSerializer<CacheEntry> contentSerializer = new Jackson2JsonRedisSerializer<>(CacheEntry.class);
RedisTemplate<String, CacheEntry> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(stringSerializer);
template.setHashKeySerializer(stringSerializer);
template.setHashValueSerializer(contentSerializer);
template.setValueSerializer(contentSerializer);
template.setEnableDefaultSerializer(false);
template.afterPropertiesSet();
return template;
}
private RedisTemplate<String, String> stringRedisTemplate()
{
StringRedisSerializer stringSerializer = new StringRedisSerializer(StandardCharsets.UTF_8);
Jackson2JsonRedisSerializer<String> contentSerializer = new Jackson2JsonRedisSerializer<>(String.class);
RedisTemplate<String, String> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(stringSerializer);
template.setHashKeySerializer(stringSerializer);
template.setHashValueSerializer(contentSerializer);
template.setValueSerializer(contentSerializer);
template.setEnableDefaultSerializer(false);
template.afterPropertiesSet();
return template;
}
}
* 也可以进一步封装一个操作类OeeResourceCache,和一个数据类CacheEntry(包含创建时间)作为value放到redis中
@Configuration
public class OeeResourceCacheConfig {
@Autowired
private RedisRepository redisRepository;
@Autowired
private RedisSetRepository redisSetRepository;
@Bean
public OeeResourceCache oeeResourceCache() {
return new OeeResourceCache(redisRepository);
}
@Bean
public SynchronizationCache synchronizationCache() {
return new SynchronizationCache(redisSetRepository);
}
}
public class OeeResourceCache {
private static final Logger LOG = LoggerFactory.getLogger(OeeResourceCache.class);
private static final String OEE_RESOURCE_KEY = "oeeResource";
private RedisRepository redisRepository;
public OeeResourceCache(RedisRepository redisRepository) {
this.redisRepository = redisRepository;
}
public void cacheOeeResource(String tenantId, String assetId, OeeResource oeeResource) {
LOG.debug("Caching OeeResource for tenant {}, assetId {}", tenantId, assetId);
LOG.trace("OeeResource: {}", oeeResource);
Check.notNull(tenantId, "tenantId");
Check.notNull(assetId, "assetId");
String key = getKey(tenantId, assetId);
CacheEntry cacheEntry = redisRepository.put(key, CacheEntry.from(oeeResource.toTimeSeriesValue()));
LOG.info("OeeResource is cached for tenant {}, assetId {}", tenantId, assetId);
LOG.trace("CacheEntry: {}", cacheEntry);
}
public OeeResource getOeeResource(String tenantId, String assetId) {
LOG.debug("Getting OeeResource from cache for tenant {}, assetId {}", tenantId, assetId);
Check.notNull(tenantId, "tenantId");
Check.notNull(assetId, "assetId");
String key = getKey(tenantId, assetId);
CacheEntry cacheEntry = redisRepository.get(key);
LOG.trace("CacheEntry: {}", cacheEntry);
return cacheEntry == null ? null : OeeResource.from(cacheEntry.to(TimeSeriesValue.class));
}
public Optional<OeeResource> getOeeResource(String tenantId, String assetId, Instant time) {
return Optional.ofNullable(getOeeResource(tenantId, assetId)).filter(Objects::nonNull)
.filter(oeeResource -> oeeResource.getDate().equals(time));
}
private String getKey(String tenantId, String assetId) {
return String.join(":", OEE_RESOURCE_KEY, tenantId, assetId);
}
}
@Getter
@Setter
@ToString
public class CacheEntry {
private String data;
@JsonInstant
private Instant createdAt;
public static CacheEntry from(Object object) {
CacheEntry entry = new CacheEntry();
entry.setCreatedAt(Instant.now());
entry.setData(Misc.serializeSafeJson(object));
return entry;
}
public <T> T to(Class<T> theClass) {
return Misc.deserializeSafeJson(data, theClass);
}
}
Spring Boot - Spring Cache的更多相关文章
- spring boot guava cache 缓存学习
http://blog.csdn.net/hy245120020/article/details/78065676 ****************************************** ...
- spring Boot+spring Cloud实现微服务详细教程第二篇
上一篇文章已经说明了一下,关于spring boot创建maven项目的简单步骤,相信很多熟悉Maven+Eclipse作为开发常用工具的朋友们都一目了然,这篇文章主要讲解一下,构建spring bo ...
- spring Boot+spring Cloud实现微服务详细教程第一篇
前些天项目组的大佬跟我聊,说项目组想从之前的架构上剥离出来公用的模块做微服务的开发,恰好去年的5/6月份在上家公司学习了国内开源的dubbo+zookeeper实现的微服务的架构.自己平时对微服务的设 ...
- Spring boot +Spring Security + Thymeleaf 认证失败返回错误信息
[Please make sure to select the branch corresponding to the version of Thymeleaf you are using] Stat ...
- 255.Spring Boot+Spring Security:使用md5加密
说明 (1)JDK版本:1.8 (2)Spring Boot 2.0.6 (3)Spring Security 5.0.9 (4)Spring Data JPA 2.0.11.RELEASE (5)h ...
- 256.Spring Boot+Spring Security: MD5是加密算法吗?
说明 (1)JDK版本:1.8 (2)Spring Boot 2.0.6 (3)Spring Security 5.0.9 (4)Spring Data JPA 2.0.11.RELEASE (5)h ...
- Spring Boot+Spring Security:获取用户信息和session并发控制
说明 (1)JDK版本:1.8(2)Spring Boot 2.0.6(3)Spring Security 5.0.9(4)Spring Data JPA 2.0.11.RELEASE(5)hiber ...
- Cola Cloud 基于 Spring Boot, Spring Cloud 构建微服务架构企业级开发平台
Cola Cloud 基于 Spring Boot, Spring Cloud 构建微服务架构企业级开发平台: https://gitee.com/leecho/cola-cloud
- spring boot + spring batch 读数据库文件写入文本文件&读文本文件写入数据库
好久没有写博客,换了一家新公司,原来的公司用的是spring,现在这家公司用的是spring boot.然后,项目组布置了一个任务,关于两个数据库之间的表同步,我首先想到的就是spring batch ...
- Spring Boot/Spring Cloud、ESB、Dubbo
如何使用Spring Boot/Spring Cloud 实现微服务应用spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现. ...
随机推荐
- Python之路,Day9 , IO多路复用(番外篇)
同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. 本文讨论的背景是Linux环境下的network IO. ...
- LUA使用虚函数与使用回调函数
------------------虚函数overload-------------------------- --回调:寻路中格子坐标改变 CHero.OnSearchToCellsChange = ...
- Redis AOF 全持久化
简介: Redis AOF 持久化,将每次接收到更改 redis 数据的操作都记录到一个 aof 文件,当服务器意外宕机或 redis 服务器非法关闭时,不会丢失数据. 可以做到数据安全化,但是性能会 ...
- Django中的DRF框架视图集使用
1. 两个基类 1)APIView Django REST_framework 中所有视图的基类是APIView 父类是View 支持定义的属性: authentication_classes 列 ...
- JAVA heap space 内存溢出
3月28日开始使用JAVA调用SAP RFC后提示内存溢出 尝试增加set java_OPTS.....但仍然提示内存溢出 最终设置方法
- 值得一做》关于一道暴搜BZOJ1024(EASY+)
为什么要写这道题的DP捏? 原因很简单,因为为原来在openjudge上有一道题叫分蛋糕,有一个思路和这道题很像:“分锅”. 分锅:即为考虑计算当前情况的最优解时,把当前状态结果,分散为考虑当前状态的 ...
- jdk+Tomcat环境
1.Tomcat概述 Tomcat服务器由Apache提供,开源免费.安装Tomcat之前需要先安装JDK,其实无论哪一种Javaweb服务器都需要先安装JDK. Tomcat6支持Servlet2. ...
- 十大基于Docker的开发工具
http://www.infoq.com/cn/news/2014/08/top-10-open-source-docker FlynnFlynn是一个使用Go语言编写的开源PaaS平台,Flynn使 ...
- vim全局替换命令-乾颐堂
语法为 :[addr]s/源字符串/目的字符串/[option] 全局替换命令为::%s/源字符串/目的字符串/g [addr] 表示检索范围,省略时表示当前行. 如:“1,20” :表示从第1行到2 ...
- mysql json格式数据处理
1.查询字段所对应的值: SELECT c.result_http->"$.create_time",json_extract(c.result_http,"$.e ...