Spring Boot中缓存注解的配置与使用
2017-08-06 00:00
696 查看
Spring Boot中缓存注解配置与使用
首先是配置
1.在pom文件中加入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
2.主类上面加注解 @EnableCaching
在application上加 @EnableCaching,用于开启缓存功能@EnableCaching public class LgdtstpApplication { public static void main(String[] args) { SpringApplication.run(LgdtstpApplication.class, args); } }
3.在数据访问接口上,加@CacheConfig(cacheNames = "persons"),方法上加@Cacheable(key = "#id")
@CacheConfig(cacheNames = "persons")注解为Spring4新增,如果不加这个,可以只写@Cacheable(value = "persons",key = "#id")在加入缓存时以Map形式 @Cacheable中的value参数,等价于@CacheConfig中的cacheNames。 代表Map的名字
key参数代表Map中的键,加入缓存的数据为Map中的value
@CacheConfig(cacheNames = "persons") public class PersonService {
//查询个人信息 @Cacheable(key = "#id") public HttpResponseEntity queryPersonInfo(String id) { HttpResponseEntity httpResponseEntity = new HttpResponseEntity(); String str = ""; //接收查询到的个人信息 PersonInfoEntity entity1= personInfoEntityMapper.selectByPrimaryKey(id); str = "id是:"+entity1.getId()+" name是:"+entity1.getName()+" "; System.out.println(str); //用于返回数据 httpResponseEntity.setData(entity1); return httpResponseEntity; }
我理解写入缓存的Map
persons:{id:存入的数据}
配置完我们来测试下@Cacheable注解
先看下不加缓存时
正常运行程序 查询id为0的用户// @Cacheable(key = "#id") public HttpResponseEntity queryPersonInfo(String id) { HttpResponseEntity httpResponseEntity = new HttpResponseEntity(); String str = ""; //接收查询到的个人信息 PersonInfoEntity entity1= personInfoEntityMapper.selectByPrimaryKey(id); str = "id是:"+entity1.getId()+" name是:"+entity1.getName()+" "; System.out.println(str); //用于返回数据给postMan httpResponseEntity.setData(entity1); return httpResponseEntity; }
看下控制台
2017-08-06 15:44:57.694 [http-nio-8080-exec-1] DEBUG c.a.l.d.P.selectByPrimaryKey -==> Preparing: select _id, user_id, name, sex, birth, phone_number, email, skill_tag, credit_score, address, head_pic_url, create_time, modify_time, production_pic_url, video_url,status , introduction from person_info_t where _id = ? 2017-08-06 15:44:57.718 [http-nio-8080-exec-1] DEBUG c.a.l.d.P.selectByPrimaryKey -==> Parameters: 0(String) 2017-08-06 15:44:57.733 [http-nio-8080-exec-1] DEBUG c.a.l.d.P.selectByPrimaryKey -<== Total: 1 id是:0 name是:铜蛋
执行了1次查询语句 ,输出数据信息,看看postMan中的返回结果
{ "code": null, "data": { "id": "0", "userId": "0", "name": "铜蛋",
接下来我们去数据库中修改name为铁蛋
在执行一次查询,控制台信息如下
2017-08-06 15:44:57.694 [http-nio-8080-exec-1] DEBUG c.a.l.d.P.selectByPrimaryKey -==> Preparing: select _id, user_id, name, sex, birth, phone_number, email, skill_tag, credit_score, address, head_pic_url, create_time, modify_time, production_pic_url, video_url,status , introduction from person_info_t where _id = ? 2017-08-06 15:44:57.718 [http-nio-8080-exec-1] DEBUG c.a.l.d.P.selectByPrimaryKey -==> Parameters: 0(String) 2017-08-06 15:44:57.733 [http-nio-8080-exec-1] DEBUG c.a.l.d.P.selectByPrimaryKey -<== Total: 1 id是:0 name是:铜蛋 2017-08-06 15:57:07.351 [http-nio-8080-exec-5] DEBUG c.a.l.d.P.selectByPrimaryKey -==> Preparing: select _id, user_id, name, sex, birth, phone_number, email, skill_tag, credit_score, address, head_pic_url, create_time, modify_time, production_pic_url, video_url,status , introduction from person_info_t where _id = ? 2017-08-06 15:57:07.351 [http-nio-8080-exec-5] DEBUG c.a.l.d.P.selectByPrimaryKey -==> Parameters: 0(String) 2017-08-06 15:57:07.354 [http-nio-8080-exec-5] DEBUG c.a.l.d.P.selectByPrimaryKey -<== Total: 1 id是:0 name是:铁蛋
postMan返回信息为
{ "code": null, "data": { "id": "0", "userId": "0", "name": "铁蛋",
总结一下,两次查询,执行两次语句,操作两次数据库,当数据库中name值变化的时候,返回的结果为修改后的name值
接下来加上缓存
@Cacheable(key = "#id") public HttpResponseEntity queryPersonInfo(String id) { HttpResponseEntity httpResponseEntity = new HttpResponseEntity(); String str = ""; //接收查询到的个人信息 PersonInfoEntity entity1= personInfoEntityMapper.selectByPrimaryKey(id); str = "id是:"+entity1.getId()+" name是:"+entity1.getName()+" "; System.out.println(str); //用于返回数据 httpResponseEntity.setData(entity1); return httpResponseEntity; }
运行第一次查询,查询id为0的用户信息,控制台输出信息如下
2017-08-06 16:03:33.956 [http-nio-8080-exec-1] DEBUG c.a.l.d.P.selectByPrimaryKey -==> Preparing: select _id, user_id, name, sex, birth, phone_number, email, skill_tag, credit_score, address, head_pic_url, create_time, modify_time, production_pic_url, video_url,status , introduction from person_info_t where _id = ? 2017-08-06 16:03:33.979 [http-nio-8080-exec-1] DEBUG c.a.l.d.P.selectByPrimaryKey -==> Parameters: 0(String) 2017-08-06 16:03:33.995 [http-nio-8080-exec-1] DEBUG c.a.l.d.P.selectByPrimaryKey -<== Total: 1 id是:0 name是:铁蛋
postMan中返回的信息如下
{ "code": null, "data": { "id": "0", "userId": "0", "name": "铁蛋",
接下来我们去数据库中修改name值,把铁蛋改为铜蛋,再次执行查询,看看控制台(此处划重点)
2017-08-06 16:03:33.956 [http-nio-8080-exec-1] DEBUG c.a.l.d.P.selectByPrimaryKey -==> Preparing: select _id, user_id, name, sex, birth, phone_number, email, skill_tag, credit_score, address, head_pic_url, create_time, modify_time, production_pic_url, video_url,status , introduction from person_info_t where _id = ? 2017-08-06 16:03:33.979 [http-nio-8080-exec-1] DEBUG c.a.l.d.P.selectByPrimaryKey -==> Parameters: 0(String) 2017-08-06 16:03:33.995 [http-nio-8080-exec-1] DEBUG c.a.l.d.P.selectByPrimaryKey -<== Total: 1 id是:0 name是:铁蛋
这时发现只有第一次查询时输出的信息,刚刚更改数据库后执行的查询,根本没有输出,来看下postMan
{ "code": null, "data": { "id": "0", "userId": "0", "name": "铁蛋",
返回的结果还是铁蛋,可我们刚才修改数据库中的name值,明明把铁蛋改为了铜蛋,为什么返回的还是铁蛋呢?
这是因为注解@Cacheable(key = "#id")的作用,当调用标注的方法时会先查看缓存中是否有数据
如果有数据,则直接返回缓存数据;若没有数据,执行该方法并将方法返回值放进缓存。
所以我们第二次查询实际上根本没有去查询数据库,而是将第一次查询存入的缓存返了回来,这样就减少了对操作数据库的压力。
但问题依然存在,数据库中的值变更了,但返回的依然是变更前的数据,造成了数据不同步,这要怎么解决呢?我们可以用另一个注解去处理这个问题。
@CachePut注解的应用
刚刚我们是直接在数据库中修改了name值,这次我们调用一个带有@CachePut注解的方法,@CachePut注解的作用和Cacheable相似,只是带有@CachePut注解的方法在执行后,会将返回值存入缓存中。也就是说当我修改了数据库,就把修改后返回的值放入缓存中,相当于刷新了之前的缓存。要注意的是,@CachePut中key参数的值要和@Cacheable中的key对应上,这样才能保证数据被放入Map中同一个Key对应的value中调用修改姓名的方法,将姓名改为彩蛋
//修改个人基本信息 @CachePut(key = "#personInfoEntity.id") public HttpResponseEntity alterBasicInfomation(PersonInfoEntity personInfoEntity) { HttpResponseEntity httpResponseEntity = new HttpResponseEntity(); logger.info("修改个人基本资料"); Date nowDate = new Date(); personInfoEntity.setModifyTime(nowDate); int number = personInfoEntityMapper.updateByPrimaryKeySelective(personInfoEntity); if (number != -1) { logger.info("修改个人基本资料成功"); httpResponseEntity.setCode(Constans.SUCCESS_CODE); } else { logger.info("修改个人基本资料失败"); httpResponseEntity.setCode(Constans.ALTER_BASIC_INFOMATION_ERROR_CODE); httpResponseEntity.setMessage(Constans.ALTER_BASIC_INFOMATION_ERROR_CMESSAGE); } //修改后查询该条信息,将修改后的数据同步给缓存和前端 PersonInfoEntity personInfoEntity1 = personInfoEntityMapper.selectByPrimaryKey(personInfoEntity.getId()); httpResponseEntity.setData(personInfoEntity1); //返回修改后的数据,返回的结果会被CachePut放入缓存,同步数据 return httpResponseEntity; }
修改成功,
再次执行查询,控制台依然没有执行语句操作数据库,而是直接从缓存中读取了,postMan中返回数据如下
{ "code": "200", "data": { "id": "0", "userId": "0", "name": "彩蛋",
读取数据为修改后的数据,同步成功。
总结:当调用带有@CachePut注解的方法时,总是会执行该方法,并且把返回的结果同步给缓存,查询的时候,因为缓存中的数据被同步了,所以就不会造成数据被修改,但查询的还是之前数据这种bug。
最后放上注解详解,方便以后查看
@CacheConfig:主要用于配置该类中会用到的一些共用的缓存配置。在这里@CacheConfig(cacheNames = "users"):配置了该数据访问对象中返回的内容将存储于名为users的缓存对象中,我们也可以不使用该注解,直接通过@Cacheable自己配置缓存集的名字来定义。
@Cacheable:配置了findByName函数的返回值将被加入缓存。同时在查询时,会先从缓存中获取,若不存在才再发起对数据库的访问。该注解主要有下面几个参数:
value、cacheNames:两个等同的参数(cacheNames为Spring 4新增,作为value的别名),用于指定缓存存储的集合名。由于Spring 4中新增了@CacheConfig,因此在Spring 3中原本必须有的value属性,也成为非必需项了
key:缓存对象存储在Map集合中的key值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如:@Cacheable(key = "#p0"):使用函数第一个参数作为缓存的key值,更多关于SpEL表达式的详细内容可参考官方文档
condition:缓存对象的条件,非必需,也需使用SpEL表达式,只有满足表达式条件的内容才会被缓存,比如:@Cacheable(key = "#p0", condition = "#p0.length() < 3"),表示只有当第一个参数的长度小于3的时候才会被缓存。
unless:另外一个缓存条件参数,非必需,需使用SpEL表达式。它不同于condition参数的地方在于它的判断时机,该条件是在函数被调用之后才做判断的,所以它可以通过对result进行判断。
keyGenerator:用于指定key生成器,非必需。若需要指定一个自定义的key生成器,我们需要去实现org.springframework.cache.interceptor.KeyGenerator接口,并使用该参数来指定。需要注意的是:该参数与key是互斥的
cacheManager:用于指定使用哪个缓存管理器,非必需。只有当有多个时才需要使用
cacheResolver:用于指定使用那个缓存解析器,非必需。需通过org.springframework.cache.interceptor.CacheResolver接口来实现自己的缓存解析器,并用该参数指定。
@CachePut:配置于函数上,能够根据参数定义条件来进行缓存,它与@Cacheable不同的是,它每次都会真是调用函数,所以主要用于数据新增和修改操作上。它的参数与@Cacheable类似,具体功能可参考上面对@Cacheable参数的解析
@CacheEvict:配置于函数上,通常用在删除方法上,用来从缓存中移除相应数据。除了同@Cacheable一样的参数之外,它还有下面两个参数:
allEntries:非必需,默认为false。当为true时,会移除所有数据
beforeInvocation:非必需,默认为false,会在调用方法之后移除数据。当为true时,会在调用方法之前移除数据。
注解详解出自:http://www.jianshu.com/p/64f684bd0ce9,里面还有关于EhCacheManager的配置。
相关文章推荐
- Spring Boot中的缓存支持(一)注解配置与EhCache使用
- Spring Boot中的缓存支持(一)注解配置与EhCache使用
- Spring Boot中的缓存支持(一)注解配置与EhCache使用
- Spring Boot中的缓存支持(一)注解配置与EhCache使用
- Spring Boot中缓存注解的配置与使用
- Spring Boot中的缓存支持(一)注解配置与EhCache使用
- Spring Boot中的缓存支持(一)注解配置与EhCache使用
- springboot使用注解配置filter以及对象转换
- Spring Boot中使用MyBatis注解配置详解
- Spring Boot 基于注解的 Redis 缓存使用
- Spring Boot学习(九)之Spring Boot中使用MyBatis注解配置详解
- spring boot 注解方式配置多数据源与使用
- spring boot:使用@ConfigurationProperties注解加载配置文件
- Spring Boot中使用MyBatis注解配置详解
- Spring Boot 中使用 @Transactional 注解配置事务管理
- Spring Boot中使用MyBatis注解配置详解
- Springboot 中同时使用mybatis注解和springbean-xml配置方式
- Redis系列三 - Spring boot如何使用redis做缓存及缓存注解的用法总结
- spring-boot使用注解获取配置文件中的值
- Spring Boot中使用MyBatis注解配置详解