一、需求分析
小程序的菜品、套餐等信息都是直接从数据库查得,若当好多用户一起访问这个数据库,会导致数据库查询性能下降,这时我们需要将这些信息存放到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();
}
}