相关依赖
导入chache依赖 和 redis依赖
一 背景
Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。 Spring Cache 提供了一层抽象,底层可以切换不同的缓存实现。
例如:1 EHCache 2 Caffeine 3 Redis
如果没有这项技术,我们在缓存的时候,需要手动的去操作如何缓存。在这里主要操作的是Redis.我们需要手动去CRUD,很麻烦。这时候用到这个技术会让开发更加便捷。他的底层用到的是一个动态代理技术,会自动创建一个代理类。在执行操作时,先访问代理类,在访问实际的类。
官网:Getting Started | Caching Data with Spring
二 常用注解介绍![](https://i-blog.csdnimg.cn/direct/50b68bce569c4269945d892176c3c973.png)
1 本章用例介绍
Controller类
package com.itheima.controller;
import com.itheima.entity.User;
import com.itheima.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@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;
}
}
user类
package com.itheima.entity;
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private int age;
}
mapper类
package com.itheima.mapper;
import com.itheima.entity.User;
import org.apache.ibatis.annotations.*;
@Mapper
public interface UserMapper{
@Insert("insert into user(name,age) values (#{name},#{age})")
@Options(useGeneratedKeys = true,keyProperty = "id")
void insert(User user);
@Delete("delete from user where id = #{id}")
void deleteById(Long id);
@Delete("delete from user")
void deleteAll();
@Select("select * from user where id = #{id}")
User getById(Long id);
}
sql建表语句
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`id`)
);
2 @EnableCaching
开启缓存注解功能,通常加在启动类上
@RestController
@RequestMapping("/user")
@Slf4j
@EnableCaching//开启缓存
public class UserController {
3 @Cacheable
在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,调用方法并将方法返回值放到缓存中
@PostMapping
@Cacheable(cacheNames = "userCache", key = "#id")
public User save(@RequestBody User user){
userMapper.insert(user);
return user;
}
有两个常用参数,cacheNames , key
两个参数最终在redis上组合生成 key 的名字: userCache::id
其中,两个的参数值都是可以自定义的,但是要按照规范。key采用动态生成值,来避免生成的key一样从而覆盖了
在key上还有其他不同种写法来看一下源码
源码:
大概有这几种可以用的,最后一个是可以获得多个参数的
@PostMapping
// @Cacheable(cacheNames = "userCache", key = "#id")
// @Cacheable(cacheNames = "userCache", key = "#result.id")
// @Cacheable(cacheNames = "userCache", key = "#root.args[0]")
@Cacheable(cacheNames = "userCache", key = "#root.args[0]")
public User save(@RequestBody User user){
userMapper.insert(user);
return user;
}
来看看redis
他的文件是树状的,中间的Empty对应着 “::” 两个冒号中间的空,如果在redis中操作,在冒号中间加上东西是可以的。
还有一个问题~(老爹附身):
这是解读:在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,调用方法并将方法返回值放到缓存中。里面暗藏玄鸡!
在没有缓存数据时,我去调用这个方法,是会进去方法里面的。
当我再次使用这个方法,这时缓存已经有数据了,他不会进入该方法。因为前面提过,他会先进对代理对象类找,找到了就直接返回缓存数据,不会再进入方法来。
当有数据时,
4 @CachePut
将方法的返回值放到缓存中,参数与@Cacheable一致
@GetMapping
@CachePut(cacheNames = "userCache", key = "#id")
public User getById(Long id){
User user = userMapper.getById(id);
return user;
}
5 @CacheEvict
将一条或多条数据从缓存中删除
@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();
}