![]()
简介
Spring 定义 CacheManager 和 Cache 接口用来统一不同的缓存技术。例如 JCache、 EhCache、 Hazelcast、 Guava、 Redis 等。在使用 Spring 集成 Cache 的时候,我们需要注册实现的 CacheManager 的 Bean。Spring Boot 默认使用的是 SimpleCacheConfiguration,即使用 ConcurrentMapCacheManager 来实现的缓存。
CacheManager:缓存管理器,管理各种缓存组件
| CacheManager |
描述 |
| SimpleCacheManager |
使用检点 Collection 来存储缓存,主要用于测试 |
| ConcurrentMapCacheManager |
使用 ConcurrentMap 存储缓存 |
| NoOpCacheManager |
仅用于测试,不会实际存储缓存 |
| EhCacheCacheManager |
使用 EhCache 作为缓存技术 |
| GuavaCacheManager |
使用 Guava 作为缓存技术 |
| HazelcastCacheManager |
使用 Hazelcast 作为缓存技术 |
| JCacheCacheManager |
支持 JCache(JSR-107)标准的实现作为缓存技术 |
| RedisCacheManager |
使用 Redis 作为缓存技术 |
Cache 注解详解
1. @CacheConfig
@CacheConfig:主要用于配置该类中会用到的一些共用的缓存配置。
在这里 @CacheConfig(cacheNames = “users”):配置了该数据访问对象中返回的内容将存储于名为 users 的缓存对象中,我们也可以不使用该注解,直接通过 @Cacheable 自己配置缓存集的名字来定义。
2. @Cacheable
@Cacheable:主要针对方法配置,能够根据方法的请求参数对其结果进行缓存。同时在查询时,会先从缓存中获取,若不存在才再发起对数据库的访问。该注解主要有下面几个参数:
3. @CachePut
@CachePut:配置于方法上,能够根据参数定义条件来进行缓存,它与 @Cacheable 不同的是,它不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入缓存中,所以主要用于数据新增和修改操作上。它的参数与 @Cacheable 类似,具体功能可参考上面对 @Cacheable 参数的解析。
4. @CacheEvict
@CacheEvict:配置于函数上,通常用在删除方法上,用来从缓存中移除相应数据。除了同 @Cacheable 一样的参数之外,它还有下面两个参数:
- allEntries:非必需,默认为 false。当为 true 时,会移除所有数据。
- beforeInvocation:非必需,默认为 false,会在调用方法之后移除数据;当为 true 时,会在调用方法之前移除数据。
搭建 Spring Boot 默认缓存
1. 开启缓存支持
在启动类上添加 @EnableCaching 开启缓存支持,进行自动扫描。
@SpringBootApplication
@EnableCaching // 开启缓存功能
public class CacheApplication {
public static void main(String[] args) {
SpringApplication.run(CacheApplication.class, args);
}
}
2. 添加 spring-boot-starter-cache 依赖
在 pom.xml 中添加 spring-boot-starter-cache 依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
3. 准备数据
模拟数据库数据
/**
* 数据工厂,模拟数据库的数据
*
* @author star
**/
public class DataFactory {
private DataFactory() {
}
private static List<UserDto> userDtoList;
static {
// 初始化集合
userDtoList = new ArrayList<>();
UserDto user = null;
for (int i = 0; i < 10; i++) {
user = new UserDto();
user.setName("star" + i);
user.setAge("2" + i);
userDtoList.add(user);
}
}
public static List<UserDto> getUserDaoList() {
return userDtoList;
}
}
编写缓存业务代码
/**
* UserRepository
*
* @author star
**/
@Repository
public class UserRepository {
/**
* 获取用户信息(此处是模拟的数据)
*/
public UserDto getUser(String username) {
UserDto user = getUserFromList(username);
return user;
}
/**
* 删除用户信息
*/
public List<UserDto> deleteUser(String username) {
List<UserDto> userDaoList = DataFactory.getUserDaoList();
userDaoList.remove(getUserFromList(username));
return userDaoList;
}
/**
* 新增数据
*/
public List<UserDto> save(String username) {
// 添加到集合
List<UserDto> userDaoList = DataFactory.getUserDaoList();
for (UserDto userDto : userDaoList) {
// 不能重复添加相同数据
if (Objects.equals(userDto.getName(), username)) {
return userDaoList;
}
}
UserDto user = new UserDto();
user.setName(username);
user.setAge("50");
userDaoList.add(user);
return userDaoList;
}
/**
* 从模拟的数据集合中筛选 username 的数据
*/
private UserDto getUserFromList(String username) {
List<UserDto> userDaoList = DataFactory.getUserDaoList();
for (UserDto user : userDaoList) {
if (Objects.equals(user.getName(), username)) {
return user;
}
}
return null;
}
}
/**
* UserService
*
* @author star
**/
@Service
@CacheConfig(cacheNames = "users")// 指定缓存名称,在本类中是全局的
public class UserService {
@Autowired
private UserRepository userRepository;
/**
* 缓存 key 是 username 的数据到缓存 users 中,
* 如果没有指定 key,则方法参数作为 key 保存到缓存中
*/
@Cacheable(key = "#username")
public UserDto getUser(String username) {
System.out.println("从数据库中获取数据,而不是读取缓存");
return userRepository.getUser(username);
}
/**
* 新增或更新缓存中的数据
*/
@CachePut(key = "#username")
public List<UserDto> save(String username) {
return userRepository.save(username);
}
/**
* 从缓存 users 中删除 key 是 username 的数据
*/
@CacheEvict(key = "#username")
public List<UserDto> deleteUser(String username) {
System.out.println("从数据库中删除数据,以及缓存中的数据");
return userRepository.deleteUser(username);
}
}
/**
* CacheResource
*
* @author star
**/
@RestController
@RequestMapping("/api")
public class CacheResource {
@Autowired
private UserService userService;
@GetMapping("/users/{username}")
public ResponseEntity<UserDto> getUser(@PathVariable String username) {
// 获取数据
UserDto user = userService.getUser(username);
return ResponseEntity.ok(user);
}
@PutMapping("/users/{username}")
public ResponseEntity<List<UserDto>> save(@PathVariable String username) {
List<UserDto> userDtoList = userService.save(username);
return ResponseEntity.ok(userDtoList);
}
@DeleteMapping("/users/{username}")
public ResponseEntity<List<UserDto>> delete(@PathVariable String username) {
List<UserDto> userDtoList = userService.deleteUser(username);
return ResponseEntity.ok(userDtoList);
}
}
启动服务:
访问:http://localhost:8080/api/users/star1