不知道有没有人会问,本地缓存有必要和spring boot结合在一起吗?自己写个Map不就可以了?答案是当然可以,但是不优雅,因为全是硬编码。他是有多优雅,看看就知道了。还是老样子,看看pom中的定义
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-web
org.springframework
spring-context
org.springframework
spring-context-support
com.google.guava
guava
org.projectlombok
lombok
spring-context中主要提供了Cache的抽象接口。spring-context-support提供了Cache的具体的实现,我们本文使用的是Google的Guava实现。声明一个配置类,设置一个CacheManager的Bean
package com.shuqi;
import com.google.common.cache.CacheBuilder;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.guava.GuavaCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager localCacheManager() {
SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
//用户缓存一天
GuavaCache ONE_DAY = new GuavaCache(
"ONE_DAY",
CacheBuilder
.newBuilder()
.expireAfterWrite(1, TimeUnit.DAYS)
.build()
);
simpleCacheManager.setCaches(Arrays.asList(ONE_DAY));
return simpleCacheManager;
}
}
设置了一个缓存区,名称叫做ONE_DAY,缓存时间是1天。我们具体使用的方式,请看我们的Controller
package com.shuqi.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class HelloController {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
@Cacheable(cacheNames = "ONE_DAY", key = "'hello name:'+#name+',age:'+#age", unless = "#result==null")
public String hello(@RequestParam String name, @RequestParam Integer age) {
log.info("HelloController hello,name:{},age:{}", name, age);
return "我的名字叫" + name + ",年龄是" + age;
}
}
注意@Cacheable(cacheNames = "ONE_DAY", key = "'hello name:'+#name+',age:'+#age", unless = "#result==null")
,这个注解说的是,例如第一次的请求name为shuqi,age为26,那么会先从ONE_DAY的缓存中,查找key为hello name:shuqi,age:26的key,如果存在了就返回,不存在就走正常的逻辑,返回:我的名字叫shuqi,年龄是26,然后放入缓存,key就是hello name:shuqi,age:26,value就是我的名字叫shuqi,年龄是26,只要不过期,那么下次有相同请求数据过来的话,就会先从缓存中获取。通过描述我们也能知道他的实现一定是通过AOP。
这种扩展方式极为优雅,不需要我们硬编码。另外补充一点,这种方式不是本地缓存特有的,我们想一下,如果CacheManager换成Redis的实现,那么是不是也就通分布式缓存挂钩了呢,留给大家自己玩吧。
下节将的内容是:SpringBoot基础教程(六)——与Dubbo的结合
本节项目源码