文章目录
1. 引入缓存依赖
<!---->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--这边用的是Redis缓存,所以加上这个依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. application.properties 配置
spring:
cache:
type: redis
redis:
database: 5
host: 192.168.25.129
port: 6379
password: 123456
3. 准备基本的Controller、Service代码
public interface RedisService {
String getString(String name);
}
@Service
public class RedisServiceImpl implements RedisService {
@Override
public String getString(String name) {
return "hello " + name;
}
}
@RestController
@RequestMapping("/redis")
public class RedisController {
@Autowired
private RedisService redisService;
@RequestMapping("/getString1")
public String getString1(@RequestParam String name){
return redisService.getString(name);
}
}
4. @Cacheable注解
4.1 cacheNames和value
指定缓存的名字,可以通过数组的方式指定多个缓存。
@AliasFor("cacheNames")
String[] value() default {};
@AliasFor("value")
String[] cacheNames() default {};
修改前面的代码,在ServiceImpl的方法上,加上@Cacheable注解并指定value属性
@Override
@Cacheable(value = {"REDIS:GETSTRING1"})
public String getString(String name) {
return "hello " + name;
}
运行SpringBoot程序,在浏览器输入 http://localhost:99/redis/getString1?name=fuhb,然后查看Redis缓存确认是否生成对应的key
127.0.0.1:6379[5]> KEYS *
1) "REDIS:GETSTRING1::fuhb"
由此可见,默认会以 value + 参数的格式生成 Redis Key。
如果是多个参数的情况下,Redis Key会是什么格式呢?
@RequestMapping("/getString2")
public String getString2(@RequestParam String name){
return redisService.getString(name, "test");
}
@Override
@Cacheable(value = {"REDIS:GETSTRING2"})
public String getString(String name, String tag) {
return tag + " " + name;
}
同样的,在浏览器输入 http://localhost:99/redis/getString2?name=fuhb,再查看Redis Key信息
127.0.0.1:6379[5]> KEYS *
1) "REDIS:GETSTRING2::SimpleKey [fuhb,test]"
2) "REDIS:GETSTRING1::fuhb"
由此可见,参数以 SimpleKey [参数拼接] 的格式进行组合。所以,接下来讲一下 key 和 keyGenerator 属性的使用
4.2 key 和 keyGenerator
keyGenerator
SpringBoot默认使用的是SimpleKeyGenerator生成key,其生成规则如下:
- 当参数为空时,返回空
- 当参数只有一个时,返回第一个参数的值
- 当参数大于一个时,返回SimpleKey对象,其序列化格式上面讲过了,代码比较简单
public String toString() {
return this.getClass().getSimpleName() + " [" + StringUtils.arrayToCommaDelimitedString(this.params) + "]";
}
如果需要自定义KeyGenerator,可以参考这篇文章:@Cacheable自定义KeyGenerator
key
相较于keyGenerator,官方更推荐直接显示地指定key
@Override
@Cacheable(value = {"REDIS:GETSTRING3"}, key = "#tag + #name")
public String getString4(String tag, String name) {
return tag + " " + name;
}
或者用这种写法,p0、p1来替代参数名
@Override
@Cacheable(value = {"REDIS:GETSTRING4"}, key = "#p0 + #p1")
public String getString4(String tag, String name) {
return tag + " " + name;
}
key 和 keyGenerator 参数是互斥的,不能同时使用
4.3 cacheManager 和 cacheResolver
CacheManager,缓存管理器是用来管理(检索)一类缓存的。通常来讲,缓存管理器是与缓存组件类型相关联的。我们知道,spring 缓存抽象的目的是为使用不同缓存组件类型提供统一的访问接口,以向开发者屏蔽各种缓存组件的差异性。那么 CacheManager 就是承担了这种屏蔽的功能。spring 为其支持的每一种缓存的组件类型提供了一个默认的 manager,如:RedisCacheManager 管理 redis 相关的缓存的检索、EhCacheManager 管理 ehCache 相关的缓等。
CacheResolver,缓存解析器是用来管理缓存管理器的,CacheResolver 保持一个 cacheManager 的引用,并通过它来检索缓存。CacheResolver 与 CacheManager 的关系有点类似于 KeyGenerator 跟 key。spring 默认提供了一个 SimpleCacheResolver,开发者可以自定义并通过 @Bean 来注入自定义的解析器,以实现更灵活的检索。
大多数情况下,我们的系统只会配置一种缓存,所以我们并不需要显式指定 cacheManager 或者 cacheResolver。但是 spring 允许我们的系统同时配置多种缓存组件,这种情况下,我们需要指定。指定的方式是使用 @Cacheable 的 cacheManager 或者 cacheResolver 参数。
4.4 sync
sync=true表示同步,也就是缓存的入口将被锁住,直到上一个线程的操作完成,可以避免缓存击穿的问题。默认情况是false,也就是异步访问,初始状态下缓存不存在,如果有大量的线程同时访问,会因为没有缓存而对DB造成较大压力。
4.5 condition
缓存的条件,只有当condition返回结果为true才使用缓存。该配置支持SpEL表达式,也可以使用result表示取返回值
如下例子,只有当name的值等于admin时,才会构造并使用缓存
@Override
@Cacheable(value = {"REDIS:GETSTRING5"}, key = "#p0 + #p1", condition = "#name == 'admin'")
public String getString5(String tag, String name) {
return tag + " " + name;
}
4.6 unless
不使用缓存的条件,跟上面的condition相反
如下例子,当name的值等于admin时不使用缓存
@Override
@Cacheable(value = {"REDIS:GETSTRING6"}, key = "#p0 + #p1", unless = "#name == 'admin'")
public String getString6(String tag, String name) {
return tag + " " + name;
}