Spring 3.1引入了基于注解(annotation)的缓存(cache)技术,它本质不是一个具体的缓存实现方案,而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的个助攻annotation,就能够达到缓存方法的返回对象的效果。
特点
具备相当好的灵活性,不仅能够使用SpEL来定义缓存的key和各种condition,还提供开箱即用的缓存临时存储方案,也支持和主流的专业缓存例如EHCache、Redis、Guava的集成。
基于annotation即可使得现有代码支持缓存
开箱即用Out-Of-The-Box,不用安装和部署额外第三方组件即可使用缓存
支持Spring Express Language,能使用对象的任何属性或者方法来定义缓存的key和condition
支持AspectJ,并通过其实现任何方法的缓存支持
支持自定义key和自定义缓存管理者,具有相当的灵活性和扩展性
使用前后
使用前:
我们需要硬编码,如果切换Cache Client还需要修改代码,耦合度高,不易于维护
public String get(String key) { String value = userMapper.selectById(key); if (value != null) { cache.put(key,value); } return value; }
使用后:
基于Spring Cache注解,缓存由开发者自己配置,但不用参与到具体编码
@Cacheable(value = "user", key = "#key") public String get(String key) { return userMapper.selectById(key); }
添加依赖
需要添加redis的依赖 同上篇
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
属性配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/david2018_db?characterEncoding=utf8
username: root
password: 1234
redis:
host: 10.211.55.5 #redis服务器地址
timeout: 10000 #超时时间
database: 0 #0-15 16个库 默认0
lettuce:
pool:
max-active: 8 #最大连接数
max-wait: -1 #默认-1 最大连接阻塞等待时间
max-idle: 8 #最大空闲连接 默认8
min-idle: 0 #最小空闲连接
cache:
type: redis
spring.cache.type 一般来说是根据依赖的包自行装配,但先后顺序会对redis使用有影响,(Jcache->EhCache->Redis->Guava) 最好还是手动配置一下
实体类
public class t_user implements Serializable { private Integer id; private String username; private String password; ... }
mybatisDao
@Mapper public interface tUserDao { @Delete("delete from t_user where id = #{id}") int delete(int id); @Update("update t_user set username = #{username},password = #{password} where id = #{id}") int update(t_user user); @Select("select * from t_user where id = #{id}") t_user getById(int id); }
Service
@Service public class t_userService { @Resource private tUserDao dao; @Cacheable(value="t_user",key="#id") public t_user getById(int id) { System.out.println("进入查询方法"); return dao.getById(id); } @CacheEvict(value="t_user",key="#id") public int delete(Integer id){ System.out.println("进入删除方法"); return dao.delete(id); } @CachePut(value="t_user",key="#user.id") public int update(t_user user) { System.out.println("进入修改方法"); return dao.update(user); } }
Controller
@RequestMapping("/t_user") @RestController public class t_userController { @Autowired private t_userService service; @GetMapping("/delete") public String delete(int id){ service.delete(id); return "delete"; } @GetMapping("/update") public String update(t_user user){ service.update(user); return "update"; } @GetMapping("/getById") public String getById(int id){ return service.getById(id).toString(); } }
最后在启动类中使用@EnableCaching启动Cache
@EnableCaching @SpringBootApplication public class BootApplication{ public static void main(String[] args) { SpringApplication.run(BootApplication.class,args); } }
运行测试:http://localhost:8088/t_user/getById?id=1 输入此路径后 控制台只打印一次进入查询方法 说明缓存了 ,而修改 删除是回打印 修改了方法 和删除了的方法的,从而切面去删掉redis中缓存的数据。其中#代表是一个SpEL表达式。
根据条件操作缓存
根据条件操作好uancun内容并不影响数据库操作,条件表达式返回一个布尔值,true/false,当条件为true,则进行缓存操作,否则直接调用方法返回结果。
长度:@CachePut(value="user",key="#user.id",condition="#user.username.legnth() < 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。
注解介绍
@Cacheable(根据方法的请求参数对其结果进行缓存)
key:缓存的key,可以为空,如果指定要按照SpEL表达式编写,如果不指定,则缺省按照方法的所有参数进行组合(如:@Cacheable(value="user",key="#username"))
value:缓存的名称,在Spring 配置文件中定义,必须指定至少一个(如:@Cacheable(value="user")或者@Cacheable(value={"user1","user2"})
condition:缓存的条件,可以为空,使用SpEL编写,返回true或者false,只有为true才进行缓存(如:@Cacheable(value="user",key="#id",condition="#id < 10"))
@CachePut(根据方法的请求参数对其结果进行缓存,和@Cacheable不同的是,它每次都会触发真实方法的调用)
@CacheEvict(根据条件对缓存进行清空)
allEntries:是否清空所有缓存内容,缺省为false,如果指定为true,则方法调用后将立即清空所有缓存(如:@CacheEvict(value="user",key="#id",allEntries=true))
beforeInvocation:是否在方法执行前就清空,缺省为false,如果指定为true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法抛出异常,则不会清空缓存(如:@CacheEvict(value="user",key="#id",beforeInvocation))