spring提供的缓存框架,使用注解简化缓存代码,类似事物管理。
底层使用哪一个缓存实现就导入哪一个的以来,这里用的是Redis。还有诸如knife4j,druid,fastjson,mybatis等的依赖都要准备
org.springframework.boot
spring-boot-starter-cache
org.springframework.boot
spring-boot-starter-data-redis
按照准备的资料的步骤建数据库建表,并配置好redis连接的信息。
项目里面有一个如下的配置,用于生成接口文档。
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
/**
* 生成接口文档配置
* @return
*/
@Bean
public Docket docket(){
log.info("准备生成接口文档...");
ApiInfo apiInfo = new ApiInfoBuilder()
.title("接口文档")
.version("2.0")
.description("接口文档")
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo)
.select()
//指定生成接口需要扫描的包
.apis(RequestHandlerSelectors.basePackage("com.itheima.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
/**
* 设置静态资源映射
* @param registry
*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始设置静态资源映射...");
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
Controller层提供了如下的代码,增删改查都有。
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
@Autowired
private UserMapper userMapper;
@PostMapping
public User save(@RequestBody User user){
userMapper.insert(user);
return user;
}
@DeleteMapping
public void deleteById(Long id){
userMapper.deleteById(id);
}
@DeleteMapping("/delAll")
public void deleteAll(){
userMapper.deleteAll();
}
@GetMapping
public User getById(Long id){
User user = userMapper.getById(id);
return user;
}
}
在启动类上加入注解
@EnableCaching //开启缓存注解功能
在save方法上加入如下注解,达成新增数据时将数据插入缓存
同时这里使用springcache缓存数据时有一个规则
键值: "cacheNames::key" ,由这个注解的两个参数决定。
而一般缓存中的数据的键值都要有特定规则,key参数通常为数据id.
这里设置key参数时使用"#形参名.属性"的格式就可以动态获取实体类的属性字段。
并且还有不同的写法可以取到属性值。
使用形参名时是从传进来的user参数取到的,result是从返回值的user取到的,中间的点称为对象导航。
如果有多个参数时还有别的写法。
写p0就是取到第一个参数,p1就是第二个参数,a0也一样可以使用
还可以使用root.args[0]也是获取到第一个参数。
@PostMapping
//@CachePut(cacheNames = "userCache",key = "#user.id")
//@CachePut(cacheNames = "userCache",key = "#result.id")
//@CachePut(cacheNames = "userCache",key = "#p0.id")
//@CachePut(cacheNames = "userCache",key = "#a0.id")
@CachePut(cacheNames = "userCache",key = "#root.args[0].id")
public User save(@RequestBody User user){
userMapper.insert(user);
return user;
}
mapper层设置了主键返回。所以controller才能获取到
@Insert("insert into user(name,age) values (#{name},#{age})")
@Options(useGeneratedKeys = true,keyProperty = "id")
void insert(User user);
设置了主键自增,不需要设定id
数据成功保存到数据库和redis
redis中的key也可以做成树形结构,通过冒号实现,两个冒号导致有一个Empty.
在查询时先查缓存有没有,没有才去数据库查询。
这里没有resule关键字,因为这个是在方法执行前生效,不能获取到方法结果。
@GetMapping
@Cacheable(cacheNames = "userCache",key = "#id") //key的生成:userCache::10
public User getById(Long id){
User user = userMapper.getById(id);
return user;
}
经过测试无误,这里使用到了代理技术,加上@Cacheable注解后可以在执行前创建一个Controller的代理对象。在代理对象查询不到的话会通过反射调用会真正的目标方法getById.
清理一条或者多条缓存时使用。
删除单条数据使用key参数,删除全部键值对使用allEntries参数
@DeleteMapping
@CacheEvict(cacheNames = "userCache",key = "#id")
public void deleteById(Long id){
userMapper.deleteById(id);
}
@DeleteMapping("/delAll")
@CacheEvict(cacheNames = "userCache",allEntries = true)
public void deleteAll(){
userMapper.deleteAll();
}