Spring Cache介绍
Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
Spring Cache提供了一层抽象,底层可以切换不同的cache实现。具体就是通过CacheManager接口来统一不同的缓存技术。
CacheManager是Spring提供的各种缓存技术抽象接口。
针对不同的缓存技术需要实现不同的CacheManager:
CacheManager | 描述 |
---|---|
EhCacheCacheManager | 使用Ehcache作为缓存技术 |
GuavaCacheManager | 使用Google的GuavaCache作为缓存技术 |
RedisCacheManager | 使用Redis作为缓存技术 |
翻译成人话: 就是一个缓存框架,可以整合其他的缓存产品,使用也非常简单,只需要加注解
SpringCache常用注解
注解 | 说明 |
---|---|
@EnableCaching | 开启缓存注解功能 |
@Cacheable | 在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中 |
@CachePut | 将方法的返回值放到缓存中 |
@CacheEvict | 将一条或多条数据从缓存中删除 |
在spring boot项目中,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存支持即可。
例如,使用Redis作为缓存技术,只需要导入Spring data Redis的maven坐标即可。
使用
如果使用的是基础功能,不需要导入jar包,在spring-boot-starter-web中已经有了
比如:如果使用redis作为缓存,还需要导入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
准备工作:在启动类加上
@EnableCaching
要使用的地方注入
@Autowired
private CacheManager cacheManager;
比如我在添加的时候加个注解
package com.itheima.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.itheima.entity.User;
import com.itheima.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
@Autowired
private CacheManager cacheManager;
@Autowired
private UserService userService;
/*
* @CachePut:将方法的返回值放入缓存
* value: 缓存的名称,每个缓存名称下面可以有多个key
* key: 缓存的key
* #result表示方法的返回值
* #root.methodName 获得当前方法的名称
* 这种表达式叫 SPEL表达式
* 这个key的写法还是很灵活的,也可以#user.name
* 这里的#result.id获取的时方法的返回值的id
* 我们缓存数据往往要缓存多分,但是这个key不能混了,这个key往往都是动态的
* */
@CachePut(value = "userCache", key = "#result.id")
@PostMapping
public User save(User user){
userService.save(user);
return user;
}
/*
* 删除时 清除这个缓存
* 这三种写法都是获取方法传入时的 这个参数
* */
@CacheEvict(value = "userCache", key = "#id")
//@CacheEvict(value = "userCache", key = "#root.args[0]")
//@CacheEvict(value = "userCache", key = "#p0")
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id){
userService.removeById(id);
}
//@CacheEvict(value = "userCache", key = "#p0.id")
@CacheEvict(value = "userCache", key = "#user.id")
@PutMapping
public User update(User user){
userService.updateById(user);
return user;
}
/*
@Cacheable
* 有缓存,那就走缓存,没有那就查询,查过后再放到缓存
* condition是条件,当
* condition = "#result != null" 返回值不为空的时候才进行缓存
*
* unless 也是条件 当等于空的时候不缓存
* */
@Cacheable(value = "userCache", key = "#id", unless = "#result == null")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){
User user = userService.getById(id);
return user;
}
/*
* 动态的拼接key
* 根据不同的查寻条件,缓存中来保存不同的key
* */
@Cacheable(value = "userCache", key = "#user.id+'_'+#user.name")
@GetMapping("/list")
public List<User> list(User user){
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(user.getId() != null,User::getId,user.getId());
queryWrapper.eq(user.getName() != null,User::getName,user.getName());
List<User> list = userService.list(queryWrapper);
return list;
}
}
使用postman测试这个方法,打个断点,查看上面注入的CacheManager对象,就会找到你这里保存的缓存
注意,这里底层是基于Map实现的,它是基于内存的,重启服务过后,缓存就没了
要解决,就要把底层切换
下面把底层切换为Redis
在Spring Boot项目中使用Spring Cache的操作步骤(使用redis缓存技术):
1.导入jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
加入redis的配置
redis:
host:
port: 6379
password:
database: 0
cache:
redis:
# 设置缓存的有效期,当然有效期不是必须的
time-to-live: 1800000
测试案例还是上面那个controller,注解都一样,只是把底层做了切换