Spring Cache 整合 Redis 实现高效缓存
Spring Cache 是 Spring 框架提供的缓存抽象层,它简化了在应用中添加缓存功能的过程,允许开发者通过注解方式轻松实现缓存逻辑,而无需关注具体的缓存实现细节。缓存抽象:Spring Cache 不直接提供缓存实现,而是定义了一套接口(如Cache),支持多种缓存实现(如 Caffeine、EhCache、Redis 等)。注解驱动:通过注解(如@Cacheable@CachePut)
·
介绍
Spring Cache 是 Spring 框架提供的缓存抽象层,它简化了在应用中添加缓存功能的过程,允许开发者通过注解方式轻松实现缓存逻辑,而无需关注具体的缓存实现细节。
- 缓存抽象:Spring Cache 不直接提供缓存实现,而是定义了一套接口(如
Cache
、CacheManager
),支持多种缓存实现(如 Caffeine、EhCache、Redis 等)。 - 注解驱动:通过注解(如
@Cacheable
、@CachePut
、@CacheEvict
)声明缓存规则,无需手动编写缓存逻辑。 - 透明集成:缓存操作与业务逻辑解耦,开发者只需关注业务代码。
常用注解
-
@Cacheable
标记方法结果可被缓存。调用方法时,先检查缓存:- 若缓存存在,直接返回缓存值,不执行方法。
- 若缓存不存在,执行方法并将结果存入缓存。
@Cacheable(value = "users", key = "#id") public User getUserById(Long id) { // 从数据库查询用户 return userRepository.findById(id); }
-
@CachePut
保证方法执行,并将结果更新到缓存(常用于更新操作)。@CachePut(value = "users", key = "#user.id") public User updateUser(User user) { return userRepository.save(user); }
-
@CacheEvict
移除缓存条目(常用于删除操作)。@CacheEvict(value = "users", key = "#id") public void deleteUser(Long id) { userRepository.deleteById(id); }
-
@Caching
组合多个缓存注解(如同时更新和删除缓存)。@Caching( put = @CachePut(value = "users", key = "#user.id"), evict = @CacheEvict(value = "userList", allEntries = true) ) public User saveUser(User user) { return userRepository.save(user); }
-
@CacheConfig
在类级别统一配置缓存属性(如value
、keyGenerator
),简化方法上的注解。
@CacheConfig(cacheNames = "users")
public class UserService {
@Cacheable(key = "#id") // 无需再指定value
public User getUserById(Long id) { ... }
@CachePut(key = "#user.id")
public User updateUser(User user) { ... }
}
实现步骤
- 1.添加依赖(Maven):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
- 2.开启缓存支持:
在启动类添加@EnableCaching
注解。
@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@Slf4j
@EnableCaching//开启缓存功能
public class SkyApplication {
public static void main(String[] args) {
SpringApplication.run(SkyApplication.class, args);
log.info("server started");
}
}
- 3.配置缓存实现:
在 yml中配置Redis
- 4.注解声明缓存规则:
如:c端
/**
* 条件查询
*
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询套餐")
@Cacheable(cacheNames = "setmealCache",key = "#categoryId")//key: setmealCache::categoryId
public Result<List<Setmeal>> list(Long categoryId) {
Setmeal setmeal = new Setmeal();
setmeal.setCategoryId(categoryId);
setmeal.setStatus(StatusConstant.ENABLE);
List<Setmeal> list = setmealService.list(setmeal);
return Result.success(list);
}
管理端
/**
* 新增套餐
* @param setmealDTO
* @return
*/
@PostMapping
@ApiOperation("新增套餐")
@CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId")
public Result save(@RequestBody SetmealDTO setmealDTO){
log.info("新增套餐:{}",setmealDTO);
setmealService.saveWithDish(setmealDTO);
return Result.success();
}
/**
* 删除套餐
* @param ids
* @return
*/
@DeleteMapping
@ApiOperation("批量删除套餐")
@CacheEvict(cacheNames = "setmealCache",allEntries = true)
public Result delete(@RequestParam List<Long> ids){
log.info("批量删除套餐:{}",ids);
setmealService.deleteBatch(ids);
return Result.success();
}
/**
* 修改套餐起售停售状态
* @param status
* @param id
* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("修改套餐起售停售状态")
@CacheEvict(cacheNames = "setmealCache",allEntries = true)
public Result startOrStop(@PathVariable("status") Integer status, Long id){
log.info("套餐起售或停售:{}",id);
setmealService.startOrStop(status,id);
return Result.success();
}
- 5.确保解耦
通过上述注解方式,缓存规则(如缓存名称、缓存键、缓存更新 / 删除时机等)通过注解声明在方法上,与业务逻辑(查询、保存、删除用户的具体实现)分离,新增或修改缓存策略时,无需改动业务逻辑代码,只需调整注解参数即可,实现了缓存规则和业务逻辑的解耦。
这样就利用 Spring Cache 抽象层,以注解驱动的方式实现了高效缓存策略,让缓存操作与业务逻辑清晰分离。
注意事项
- 缓存键生成:默认使用方法参数生成键,可通过
key
属性自定义(SpEL 表达式),或配置KeyGenerator
。 - 缓存穿透:可通过空值缓存(
@Cacheable(unless = "#result == null")
)避免。 - 缓存更新:使用
@CachePut
确保缓存与数据源一致性,避免直接修改缓存。 - 分布式缓存:在分布式系统中,推荐使用 Redis 等集中式缓存,避免本地缓存(如 Caffeine)的一致性问题。
更多推荐
所有评论(0)