苍穹外卖学习day07-缓存菜品、套餐

一、需求分析

小程序的菜品、套餐等信息都是直接从数据库查得,若当好多用户一起访问这个数据库,会导致数据库查询性能下降,这时我们需要将这些信息存放到Redis中。

1.1 菜品缓存

每个分类下得菜品保存一份缓存数据。

当数据库中得菜品发生变更时,需要清除缓存。

二、菜品缓存实现

2.1 查询菜品

2.1.1 逻辑分析

构造redis中的key

查询redis中是否存在菜品数据

如果存在直接返回结果,无需查找数据库

若不存在,将其存放到redis中

2.1.2 代码实现

package com.sky.controller.user;

import com.sky.constant.StatusConstant;
import com.sky.entity.Dish;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController("userDishController")
@RequestMapping("/user/dish")
@Slf4j
@Api(tags = "C端-菜品浏览接口")
public class DishController {
    @Autowired
    private DishService dishService;
    @Autowired
    RedisTemplate redisTemplate;
    /**
     * 根据分类id查询菜品
     *
     * @param categoryId
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("根据分类id查询菜品")
    public Result<List<DishVO>> list(Long categoryId) {
        //构造redis中的key
        String key = "dish_"+categoryId;
        //查询redis中是否存在菜品数据
        List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);
        if(list!=null && !list.isEmpty()){
            //如果存在直接返回结果,无需查找数据库
            return Result.success(list);
        }
        //若不存在,查询数据库将其存放到redis中
        Dish dish = new Dish();
        dish.setCategoryId(categoryId);
        dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品
        list = dishService.listWithFlavor(dish);
        redisTemplate.opsForValue().set(key,list);
        return Result.success(list);
    }

}

2.2 清除菜品缓存数据

2.2.1 逻辑分析

在新增菜品、修改菜品、批量删除菜品、起售停售菜品时都需要将菜品的缓存数据清除。

在管理管的DishController中修改

2.2.2 代码实现

在有增删改操作的代码执行后,进行缓存清除,这里将缓存清除这个功能抽离成一个cleanCache方法。

package com.sky.controller.admin;

import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Set;

@RestController
@Slf4j
@RequestMapping("/admin/dish")
@Api(tags = "菜品相关操作")
public class DishController {

    @Autowired
    DishService dishService;
    @Autowired
    RedisTemplate redisTemplate;
    /**
     * 新增菜品
     * @param dishDTO
     * @return
     */
    @PostMapping
    @ApiOperation("新增菜品")
    public Result addDish(@RequestBody DishDTO dishDTO){
        log.info("菜品数据:{}",dishDTO);
        dishService.addDish(dishDTO);
        //新增菜品时,只有这个类型下的菜品数据会发生变更,所以只用清除当前分类下的缓存
        String key = "dish_"+dishDTO.getCategoryId();
        cleanCache(key);

        return Result.success();
    }

    /**
     * 菜品分页查询
     * @param dishPageQueryDTO
     * @return
     */
    @GetMapping("/page")
    @ApiOperation("菜品分页查询")
    public Result<PageResult> pageQuery(DishPageQueryDTO dishPageQueryDTO){
        log.info("菜品分页查询数据:{}",dishPageQueryDTO);
        PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);
        return Result.success(pageResult);
    }

    /**
     * 菜品删除
     * @param ids
     * @return
     */
    @DeleteMapping
    @ApiOperation("菜品删除")
    public Result delete(@RequestParam List<Long>ids){
        log.info("删除菜品的ids:{}",ids);
        dishService.deleteBatch(ids);

        cleanCache("dish_*");

        return Result.success();
    }

    /**
     * 修改菜品状态
     * @param status
     * @param id
     * @return
     */
    @PostMapping("/status/{status}")
    @ApiOperation("菜品状态修改")
    public Result updateStatus(@PathVariable Integer status,long id){
        log.info("菜品状态修改参数:{},{}",status,id);
        dishService.updateStatus(status,id);

        cleanCache("dish_*");

        return Result.success();
    }

    /**
     * 菜品修改
     * @param dishDTO
     * @return
     */
    @PutMapping
    @ApiOperation("菜品修改")
    public Result updateDish(@RequestBody DishDTO dishDTO){
        log.info("菜品修改数据:{}",dishDTO);
        dishService.updateDish(dishDTO);

        cleanCache("dish_*");

        return Result.success();
    }

    /**
     * 根据类型查询菜品
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("根据id查询菜品")
    public Result<DishVO> getById(@PathVariable Long id){
        log.info("查询菜品id:{}",id);
        DishVO dishVO = dishService.getByIdWithFlavors(id);
        return Result.success(dishVO);
    }

    /**
     * 根据分类id查询菜品
     * @param categoryId
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("通过分类id查询菜品")
    public Result getByCategoryId(Long categoryId){
        log.info("查询分类id:{}",categoryId);
        List<Dish> dishes = dishService.getByCategoryId(categoryId);
        return Result.success(dishes);
    }

    private void cleanCache(String patten){
        Set keys = redisTemplate.keys(patten);
        redisTemplate.delete(keys);
    }
}

三、套餐缓存实现

3.1SpringCache框架

在操作缓存数据的地方添加注解。

3.2 实现思路

3.3 代码实现

        1.启动类上添加@EnableCaching注解

        2.用户端SetmealController的list方法上添加注解

@Cacheable(cacheNames = "setmealCache",key = "#categoryId")//key=setmealCache::100

3.管理端的setmealController

package com.sky.controller.admin;

import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Setmeal;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import com.sky.vo.SetmealVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Delete;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@Slf4j
@RequestMapping("/admin/setmeal")
@Api(tags = "套餐相关操作")
public class SetmealController {

    @Autowired
    SetmealService setmealService;

    @PostMapping
    @ApiOperation("新增套餐")
    @CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.getCategoryId()")
    public Result addSetmeal(@RequestBody SetmealDTO setmealDTO){
        log.info("新增套餐数据:{}",setmealDTO);
        setmealService.addSetmeal(setmealDTO);
        return Result.success();
    }

    @GetMapping("/page")
    @ApiOperation("套餐分页查询")
    public Result<PageResult> pageQuerySetmeal(SetmealPageQueryDTO setmealPageQueryDTO){
        log.info("套餐分页查询数据:{}",setmealPageQueryDTO);
        PageResult pageResult = setmealService.pageQuery(setmealPageQueryDTO);
        return Result.success(pageResult);
    }

    @PostMapping("/status/{status}")
    @ApiOperation("套餐起售停售")
    @CacheEvict(cacheNames = "setmealCache",allEntries = true)
    public Result updateStatus(@PathVariable Integer status,Long id){
        log.info("套餐状态:{}",status);
        setmealService.updateStatus(status,id);
        return Result.success();
    }

    /**
     * 根据id查询套餐用于修改页面的数据回显
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result<SetmealVO>selectSetmealById(@PathVariable Long id){
        SetmealVO setmealVO = setmealService.selectById(id);
        return Result.success(setmealVO);
    }

    @PutMapping
    @Transactional
    @ApiOperation("修改套餐")
    @CacheEvict(cacheNames = "setmealCache",allEntries = true)
    public Result updateSetmeal(@RequestBody SetmealDTO setmealDTO){
        log.info("修改套餐数据:{}",setmealDTO);
        setmealService.updateSetmeal(setmealDTO);
        return Result.success();
    }

    @DeleteMapping
    @ApiOperation("批量删除套餐")
    @CacheEvict(cacheNames = "setmealCache",allEntries = true)
    public Result deleteBatch(@RequestParam List<Long> ids){
        log.info("删除套餐的id:{}",ids);
        setmealService.deleteBatch(ids);
        return Result.success();
    }

}

### 关于苍穹外卖 Day09 的教程或资料 目前提供的引用中并未直接提及关于苍穹外卖第9天的具体内容。然而,可以通过分析已有的参考资料来推测可能的学习方向以及相关内容。 #### 已知信息总结 1. **Swagger调试**:如果在学习过程中遇到Swagger无法正常工作的情况,可以参考【苍穹外卖Day1的相关说明[^1]。 2. **AOP实现公共字段填充**:DAY4的内容涉及通过AOP技术实现公共字段的自动填充功能[^2]。 3. **Web配置文件**:在Day3到Day5期间,`WebMvcConfiguration.java` 文件被重点讲解,涉及到Spring Boot中的Web相关配置[^3]。 4. **实体对象构建方式**:Day2的部分知识点记录了如何使用构造器模式创建实体类对象,并介绍了常见的注解如 `@PathVariable`, `@RequestParam`, 和 `@RequestBody` 等[^4]。 #### 推测Day09可能涵盖的主题 虽然具体Day09的教学内容未提供,但根据前几日的知识点分布规律,通常会逐步深入业务逻辑、优化性能或者集成第三方服务等内容。以下是几个可能的方向: - **分布式事务管理**:随着系统的复杂度增加,在多模块协作场景下可能会引入分布式事务解决方案(如Seata)。 - **缓存机制设计**:为了提升访问效率,可能会加入Redis或其他内存数据库作为缓存层。 - **消息队列应用**:处理异步任务时常用RabbitMQ/Kafka等中间件工具。 - **安全性增强措施**:比如OAuth2认证授权流程的设计与实践。 下面给出一段假设性的代码片段展示如何利用Lombok简化Java Bean定义过程的同时支持链式调用特性: ```java import lombok.Builder; import lombok.Data; @Data @Builder(toBuilder = true) public class OrderDetail { private String orderId; // 订单编号 private Integer userId; // 用户ID private Double totalAmount; // 总金额 public static void main(String[] args){ OrderDetail order = OrderDetail.builder() .orderId("20231018123456789") .userId(1001) .totalAmount(123.45d) .build(); System.out.println(order); } } ``` 此示例仅作教学用途演示,请依据实际需求调整相应属性名称及其类型定义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值