苍穹外卖day07缓存部分分析

苍穹外卖Day07部分聚焦于缓存功能的实现与优化,通过引入redis缓存机制,结合Spring Cache 注解,降低了数据库负载,提升其响应速度。

以下是清除缓存功能代码:

java 复制代码
@RestController
@RequestMapping("/admin/dish")
@Slf4j
@Api("菜品相关接口")
public class DishController {

    @Autowired
    DishService dishService;

    @Autowired
    RedisTemplate redisTemplate;

    @GetMapping("/list")
    @ApiOperation("根据分类id查询菜品")
    public Result<List<DishVO>> getByCategoryId(Long categoryId) {
        log.info("根据分类id查询菜品");
        String key = "dish:" + categoryId;
        List<DishVO> a = (List<DishVO>) redisTemplate.opsForValue().get(key);
        System.out.println(a);
        if (a != null && a.size() > 0) {
            return Result.success(a);
        }
        Dish dish = new Dish();
        dish.setCategoryId(categoryId);
        dish.setStatus(StatusConstant.DISABLE);
        a = dishService.listWithFlavor(dish);
        redisTemplate.opsForValue().set(key, a);
        return Result.success(a);
    }

    @PostMapping("/status/{status}")
    @ApiOperation("菜品起售停售")
    public Result startOrStop(@PathVariable Integer status, Long id) {
        dishService.startOrStop(status,id);
        cleanCache();
        return Result.success();
    }
    private void cleanCache() {
        Set set = redisTemplate.keys("dish:*");
        redisTemplate.delete(set);
    }
}

在startOrStop方法中,当执行菜品起售停售操作后,会调用 cleanCache 私有方法来清理 Redis 缓存。在 cleanCache 方法里,通过 Set set = redisTemplate.keys("dish:*"); 利用 Redis 的 keys 命令获取所有以 "dish:" 开头的键值,也就是获取所有与菜品相关的缓存键,然后使用 redisTemplate.delete(set),将这些键对应的缓存数据全部删除。

这样可以确保在菜品状态发生改变后,缓存中的菜品数据能及时更新,避免前端获取到旧的不符合实际状态的菜品信息,从而保证了缓存数据与数据库数据的一致性。但是使用keys命令在生产环境中如果数据量很大可能会影响性能,因为它需要遍历所有键,可以考虑采用更精准的缓存失效策略,比如根据具体变更的菜品 id 来有针对性地删除相关缓存,而不是批量删除所有菜品缓存,也可以使用Spring Cache注解。

Spring Cache

  1. @EnableCaching:加在启动类上,用于开启缓存注解功能,使得项目中可以使用Spring Cache的其他注解。
  2. @Cacheable:放在方法上,在方法执行前先查询缓存中是否存在缓存数据,存在数据直接将数据返回;没有缓存数据,通过反射调用方法并将方法的返回值放到缓存中。
  3. @CachePut:将方法的返回值放到缓存中,通常用于在方法执行完毕后更新缓存中的数据。
  4. @CacheEvict:用于将一条或多条数据从缓存中删除,可以根据具体的 key 删除指定的缓存数据,也可以使用allEntries = true 删除整个缓存名称下的所有数据。

以下为使用spring cahce注解的代码:

java 复制代码
@RestController
@RequestMapping("/admin/dish")
@Slf4j
@Api("菜品相关接口")
@EnableCaching
public class DishController {

    @Autowired
    DishService dishService;

    @Autowired
    RedisTemplate redisTemplate;

    @GetMapping("/list")
    @ApiOperation("根据分类id查询菜品")
    @Cacheable(cacheNames = "dishCache", key = "#categoryId")
    public Result<List<DishVO>> getByCategoryId(Long categoryId) {
        log.info("根据分类id查询菜品");
        Dish dish = new Dish();
        dish.setCategoryId(categoryId);
        dish.setStatus(StatusConstant.DISABLE);
        List<DishVO> a = dishService.listWithFlavor(dish);
        return Result.success(a);
    }

    @PostMapping("/status/{status}")
    @ApiOperation("菜品起售停售")
    @CacheEvict(cacheNames = "dishCache", allEntries = true)
    public Result startOrStop(@PathVariable Integer status, Long id) {
        dishService.startOrStop(status, id);
        return Result.success();
    }
}

这段代码使用@Cacheable(cacheNames = "dishCache", key = "#categoryId") 注解, cacheNames 指定了缓存的名称空间为 "dishCache",用于将菜品相关的缓存数据统一归类管理,方便后续维护与排查问题。

key = "#categoryId" 则以传入的菜品分类 id作为缓存的键,使得在查询菜品时,系统能够依据分类 id 精准地在 "dishCache" 缓存区域中查找对应数据。当缓存中有匹配的数据时,直接返回缓存数据,不再执行方法体中的数据库查询代码,大大加快了响应速度。

相关推荐
GJCTYU6 分钟前
spring中@Transactional注解和事务的实战理解附代码
数据库·spring boot·后端·spring·oracle·mybatis
艾迪的技术之路16 分钟前
redisson使用lock导致死锁问题
java·后端·面试
今天背单词了吗98034 分钟前
算法学习笔记:8.Bellman-Ford 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·开发语言·后端·算法·最短路径问题
天天摸鱼的java工程师37 分钟前
使用 Spring Boot 整合高德地图实现路线规划功能
java·后端
东阳马生架构1 小时前
订单初版—2.生单链路中的技术问题说明文档
java
咖啡啡不加糖1 小时前
暴力破解漏洞与命令执行漏洞
java·后端·web安全
风象南1 小时前
SpringBoot敏感配置项加密与解密实战
java·spring boot·后端
DKPT1 小时前
Java享元模式实现方式与应用场景分析
java·笔记·学习·设计模式·享元模式
Percep_gan1 小时前
idea的使用小技巧,个人向
java·ide·intellij-idea