一起来学 SpringBoot 2.x | 第十篇:使用 Spring Cache 集成 Redis
总阅读量:3397次
摘要: 原创出处 http://blog.battcn.com/2018/05/13/springboot/v2-cache-redis/ 「唐亚峰」欢迎转载,保留摘要,谢谢!
SpringBoot
是为了简化Spring
应用的创建、运行、调试、部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的搭建出一个 WEB 工程
Spring 3.1
引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache
或者 Redis
),而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种 annotation
,即能够达到缓存方法的返回对象的效果。
1. 特点
具备相当的好的灵活性,不仅能够使用 **SpEL(Spring Expression Language)**来定义缓存的 key 和各种 condition,还提供开箱即用的缓存临时存储方案,也支持和主流的专业缓存例如 EHCache、Redis、Guava 的集成。
- 基于 annotation 即可使得现有代码支持缓存
- 开箱即用 Out-Of-The-Box,不用安装和部署额外第三方组件即可使用缓存
- 支持 Spring Express Language,能使用对象的任何属性或者方法来定义缓存的 key 和 condition
- 支持 AspectJ,并通过其实现任何方法的缓存支持
- 支持自定义 key 和自定义缓存管理者,具有相当的灵活性和扩展性
2. 使用前后
下面针对Spring Cache
使用前后给出了伪代码部分,具体中也许比这要更加复杂,但是Spring Cache
都可以很好的应对
使用前
我们需要硬编码,如果切换Cache Client
还需要修改代码,耦合度高,不易于维护
public String get(String key) { |
使用后
基于Spring Cache
注解,缓存由开发者自己配置,但不用参与到具体编码
"user", key = "#key") (value = |
3. 添加依赖
在 pom.xml
中添加 spring-boot-starter-data-redis
的依赖
<dependency> |
4. 属性配置
在 application.properties
文件中配置如下内容,由于Spring Boot2.x
的改动,连接池相关配置需要通过spring.redis.lettuce.pool
或者 spring.redis.jedis.pool
进行配置了。使用了Spring Cache
后,能指定spring.cache.type
就手动指定一下,虽然它会自动去适配已有Cache
的依赖,但先后顺序会对Redis
使用有影响**(JCache -> EhCache -> Redis -> Guava)**
spring.redis.host=localhost |
5. 具体编码
5.1 实体类
创建一个User
类,目的是为了模拟对象存储
package com.battcn.entity; |
5.2 定义接口
package com.battcn.service; |
5.2.1 实现类
为了方便演示数据库操作,直接定义了一个Map<Long, User> DATABASES
,这里的核心就是**@Cacheable、@CachePut、@CacheEvict** 三个注解
package com.battcn.service.impl; |
5.3 主函数
@EnableCaching 必须要加,否则spring-data-cache
相关注解不会生效…
package com.battcn; |
5.4 测试
完成准备事项后,编写一个junit
测试类来检验代码的正确性,有很多人质疑过Redis
线程安全性,故下面也提供了响应的测试案例,如有疑问欢迎指正
package com.battcn; |
启动测试类,结果和我们期望的一致,可以看到增删改查中,查询是没有日志输出的,因为它直接从缓存中获取的数据,而添加、修改、删除都是会进入方法内执行具体的业务代码,然后通过切面去删除掉Redis中的缓存数据。其中 # 号代表这是一个 SpEL 表达式,此表达式可以遍历方法的参数对象,具体语法可以参考 Spring 的相关文档手册。
2018-05-14 09:20:55.303 INFO 21176 --- [ main] com.battcn.service.impl.UserServiceImpl : 进入 saveOrUpdate 方法 |
其它类型
下列的就是Redis
其它类型所对应的操作方式
- opsForValue: 对应 String(字符串)
- opsForZSet: 对应 ZSet(有序集合)
- opsForHash: 对应 Hash(哈希)
- opsForList: 对应 List(列表)
- opsForSet: 对应 Set(集合)
- opsForGeo: 对应 GEO(地理位置)
5.5 根据条件操作缓存
根据条件操作缓存内容并不影响数据库操作,条件表达式返回一个布尔值,true/false,当条件为true,则进行缓存操作,否则直接调用方法执行的返回结果。
- 长度:
@CachePut(value = "user", key = "#user.id",condition = "#user.username.length() < 10")
只缓存用户名长度少于10的数据 - 大小:
@Cacheable(value = "user", key = "#id",condition = "#id < 10")
只缓存ID小于10的数据 - 组合:
@Cacheable(value="user",key="#user.username.concat(##user.password)")
- 提前操作:
@CacheEvict(value="user",allEntries=true,beforeInvocation=true)
加上beforeInvocation=true
后,不管内部是否报错,缓存都将被清除,默认情况为false
5.6 注解介绍
@Cacheable(根据方法的请求参数对其结果进行缓存)
- key: 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合(如:
@Cacheable(value="user",key="#userName")
) - value: 缓存的名称,在 Spring 配置文件中定义,必须指定至少一个(如:
@Cacheable(value="user")
或者@Cacheable(value={"user1","use2"})
) - condition: 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存(如:
@Cacheable(value = "user", key = "#id",condition = "#id < 10")
)
@CachePut(根据方法的请求参数对其结果进行缓存,和
@Cacheable
不同的是,它每次都会触发真实方法的调用)
- key: 同上
- value: 同上
- condition: 同上
@CachEvict(根据条件对缓存进行清空)
- key: 同上
- value: 同上
- condition: 同上
- allEntries: 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存(如:
@CacheEvict(value = "user", key = "#id", allEntries = true)
) - beforeInvocation: 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存(如:
@CacheEvict(value = "user", key = "#id", beforeInvocation = true)
)
6. 总结
spring-cache文档: https://docs.spring.io/spring/docs/5.0.5.RELEASE/spring-framework-reference/integration.html#cache-introduction spring-data-redis文档: https://docs.spring.io/spring-data/redis/docs/2.0.1.RELEASE/reference/html/#new-in-2.0.0 Redis 文档: https://redis.io/documentation Redis 中文文档: http://www.redis.cn/commands.html
目前很多大佬都写过关于 SpringBoot 的教程了,如有雷同,请多多包涵,本教程基于最新的 spring-boot-starter-parent:2.0.1.RELEASE
编写,包括新版本的特性都会一起介绍…
7. 说点什么
全文代码:https://github.com/battcn/spring-boot2-learning/tree/master/chapter9
666. 彩蛋
如果你对 SpringBoot 感兴趣,欢迎加入我的知识星球一起交流。