springboot对缓存支持非常灵活,默认使用的EhCache,也可以整合第三方的框架,如redis,只需配置即可。
ehcache直接在jvm虚拟机中缓存,速度快,效率高;但是缓存共享麻烦,集群分布式应用不方便。
redis是通过socket访问到缓存服务,效率比ecache低,比数据库要快很多,处理集群和分布式缓存方便,有成熟的方案。如果是单个应用或者对缓存访问要求很高的应用,用ehcache。如果是大型系统,存在缓存共享、分布式部署、缓存内容很大的,建议用redis。
基础配置
properties文件配置注解类型即可。
spring.cache.type=redis
添加redis配置
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
pom引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Application.java类添加@EnableCaching注解开启缓存支持
常用注解
@Cacheable
-
标记在类上:表示该类所有的方法都是支持缓存的。
-
标记在方法上:如果一个方法上添加了@Cacheable标记,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。
-
@Cacheable可以指定三个属性,value、key和condition。
value必须指定,表示当前方法的返回值会被缓存在哪个Cache上,对应Cache的名称。可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。
-
unless参数的作用是:函数返回值符合表达式条件的,veto(否决)、不缓存;换句话说,函数返回值符合条件的排除掉、只缓存其余不符合条件的
-
condition参数表示满足条件的才会缓存;
-
适用场景:查询接口
//cache缓存在user命名空间下 @Cacheable(value ="user", unless = "#result eq null") public List<User> findUser() { return userRepository.findAll(userId); } // key值为方法名 @Cacheable(value ="user" key="#root.methodName" ) public List<User> findUser() { return userRepository.findAll(userId); } //key值为入参 @Cacheable(value ="user", key="#userId",unless = "#result eq null") public User findUser(String userId) { return userRepository.findById(userId).orElse(null); } //key值为入参 p0代表第一个入参p0 @Cacheable(value ="user", key="#p0",unless = "#result eq null") public User findUser(String userId) { return userRepository.findById(userId).orElse(null); } //key值为方法名+入参 @Cacheable(value ="user", key="#root.methodName+'['+#userId+']'",unless = "#result eq null") public User findUser(String userId) { return userRepository.findById(userId).orElse(null); } //key值为方法名+多个入参 @Cacheable(value ="user", key="#root.methodName+'['+#userId+','+#name+']'",unless = "#result eq null") public User findUser(String userId) { return userRepository.findById(userId).orElse(null); } //key值为入参对象的属性 @Cacheable(value ="user", key="#user.id",unless = "#result eq null") public User findUser(User user) { return userRepository.findById(userId).orElse(null); }
@CachePut
-
@CachePut也可以声明一个方法支持缓存功能。不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
-
适用场景:更新操作,插入操作,一般将此注解放在更新方法上,这样就能实时更新缓存数据,需要注意的是key和value的取值,依靠这两个参数确定到某个缓存更新。
@CachePut(value="user", key="#user.id") public User update(User user) { user = userRepository.save(user); // 必须把更新后的用户数据返回,这样才能把它缓存到redis中 return user; }
@CacheEvict
-
@CacheEvict是清除缓存的注解。其中注解参数可以只有value,key意思是清除在value值空间中的key值数据,此时默认在当前注解方法成功执行之后再清除。
-
若想删除redis缓存的所有用户数据,可以把注解改成@CacheEvict(cacheNames=“user”,allEntries=true)
//清除指定key @CacheEvict(value="user", key="#id") public boolean delete(String id) { // 可以在这里添加删除数据库对应用户数据的操作 return true; } //清除整个命名空间 @CacheEvict(value="user",allEntries=true) public boolean deleteAll() { // 可以在这里添加删除数据库对应用户数据的操作 return true; }
-
注意:beforeInvocation:是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存