文章目录
- 前言
- 缓存菜品
- 问题分析和实现思路
- 缓存菜品数据
- 清理缓存数据
- 功能测试
- SpringCache
- 介绍
- 入门案例
- 缓存套餐
前言
本章节主要是进行用户端的购物车功能开发
和redis作为mysql缓存的应用以及SpringCache的介绍
因为很多人查询数据库会导致mysql的查询效率降低,可以通过redis作为缓存来解决
实现产品原型
基本可以看出一些功能
添加购物车
查看购物车
清空购物车
以及我们进行redis应用的缓存菜品和套餐
还有一个自己的作业 就是增减购物车内商品的功能
缓存菜品
问题分析和实现思路
缓存菜品数据
这个挺简单的
就是根据redis中有无对应数据来进行操作
注意redis返回的数据类型(存入时是什么,取出来就是什么)
redis中的string可以对应java中的任意类型
@RestController("userDishController")
@RequestMapping("/user/dish")
@Slf4j
@Api(tags = "C端-菜品浏览接口")
public class DishController {
@Autowired
private DishService dishService;
@Autowired
private RedisTemplate redisTemplate;
/**
* 根据分类id查询菜品
*
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<DishVO>> list(Long categoryId) {
//构造redis中的key,规则: dish_分类id(以分类形式存储菜品)
String key = "dish_"+categoryId;
//查询redis是否存在菜品数据
List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);
if(list != null && list.size() > 0){
//如果存在,直接返回,无需查询数据库
return Result.success(list);
}
Dish dish = new Dish();
dish.setCategoryId(categoryId);
dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品
list = dishService.listWithFlavor(dish);
//如果不存在,查询数据库,讲查询到的数据库放入redis中
redisTemplate.opsForValue().set(key,list);
return Result.success(list);
}
}
清理缓存数据
有可能我们管理端会修改/删除/新增菜品
你们上一次的查询到redis的要跟着更新
要不然sql和redis中数据不一致,管理端作出的更改用户端如果还是去查redis就看不到
这里就只写
admin中DishController中修改的方法
@PostMapping
@ApiOperation("新增菜品")
public Result save(@RequestBody DishDTO dishDTO){
log.info("新增菜品:{}",dishDTO);
dishService.saveWithFlavor(dishDTO);
//清理缓存数据
cleanCache("dish_"+dishDTO.getCategoryId());
return Result.success();
}
@DeleteMapping
@ApiOperation("菜品的批量删除")
public Result delete(@RequestParam List<Long> ids){//传参为1,2,3这种,想要mvc帮我们自动封装需要用到@RequestParam,否则只能字符串接收自己解析
log.info("菜品批量删除:{}",ids);
dishService.deleteBatch(ids);
//这个比较复杂,所以直接全部删除 dish_*就表示以dish_开头的key
//需要先将对应全部key取出然后再删除
cleanCache("dish_*");
return Result.success();
}
@PutMapping
@ApiOperation("修改菜品")
public Result update(@RequestBody DishDTO dishDTO) {
log.info("修改菜品,对应信息为:{}",dishDTO);
dishService.updateWithFlavor(dishDTO);
//仔细想想更改 可以设计一个分类(只更改名称价格什么的) 也可以涉及两个(菜品分类的变更)
//所以这里也清理掉所有缓存
cleanCache("dish_*");
return Result.success();
}
@PostMapping("/status/{status}")
@ApiOperation("起售,停售菜品")
public Result startOrStop(@PathVariable Integer status,Long id){
log.info("起售停售菜品:{},{}",status,id);
dishService.startOrStop(status,id);
//这里也全部清理掉,需要查表对应分类id情况有点复杂
cleanCache("dish_*");
return Result.success();
}
这个是新增方法
/**
* 清理缓存数据
* @param pattern
*/
private void cleanCache(String pattern){
Set keys = redisTemplate.keys(pattern);
redisTemplate.delete(keys);
}
功能测试
略
看对应更换分类后有没有sql语句输出
和修改分类菜品后对应的分类菜品情况
SpringCache
介绍
admin,增删改数据只需要清除缓存,CachePut是user那边查询数据时同步缓存用的
只有需要查才会放入缓存
@Cacheable用于select(查询)
@CachePut一般用于新增
@CacheEvict就是用户端的更改,删除等等
入门案例
导入依赖
redis和springcache
其他正常的那些依赖就不介绍了
再进行一下文件配置
controller里面提起写好了方法主要是学一下springcache
往下就是使用springcache的正常流程了
1.再springboot启动类开启缓存注解
比如这个请求
我们存储用户,一般是希望同时存储到缓存中
所以我们用==@CachePut修饰==
对应的属性 cacheNames和key是与redis中的key有关的
redis中的key=cacheNames::key
key一般是动态获取,使不同用户对应不同key,可以获取user的id
格式是 key = #user(参数).id
有人可能问刚开始还没传id,怎么获取对应id,user参数和user返回值是一个,然后其实操作是先插入到sql数据库然后再进行缓存的(mybatis进行操作返回id给user对象)
也可以这样写,result引用方法的返回值
其实还有很多用法
但是还是最推荐第一种
查询相关的语句,先看redis有没有,没有查数据库的然后存到redis中
用到@Cacheable注解,这里就不能用result,具体可以看注解里有对应的注释说明
然后我们要查询的key就是userCache::id (因为我们新增就是用这个,然后查询也要用这个可以)
删除一条数据
使用@CaheEvict来进行缓存数据的删除,保障数据库和缓存的数据一致性
删除所有的缓存的键值对
把key属性变为allEntries属性并且设为true
缓存套餐
改的不多
这是admin包下的setmealController
@RestController
@RequestMapping("/admin/setmeal")
@Api("套餐相关接口")
@Slf4j
public class SetmealController {
/**
* 新增套餐
*/
@Autowired SetmealService setmealService;
@PostMapping
@ApiOperation("新增套餐")
@CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId")
public Result save(@RequestBody SetmealDTO setmealDTO){
log.info("新增套餐信息:{}",setmealDTO);
setmealService.saveWithDish(setmealDTO);
return Result.success();
}
/**
* 根据id查询套餐
* @param id
* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据id查询套餐")
public Result<SetmealVO> getById(@PathVariable Long id){
SetmealVO setmealVO = setmealService.getByIdWithDish(id);
return Result.success(setmealVO);
}
/**
* 分页查询
* @param setmealPageQueryDTO
* @return
*/
@GetMapping("/page")
@ApiOperation("分页查询")
public Result<PageResult> page(SetmealPageQueryDTO setmealPageQueryDTO){
log.info("套餐分页查询:{}",setmealPageQueryDTO);
PageResult pageResult = setmealService.pageQuery(setmealPageQueryDTO);
return Result.success(pageResult);
}
/**
* 批量删除套餐
* @param ids
* @return
*/
@DeleteMapping
@ApiOperation("批量删除套餐")
@CacheEvict(cacheNames = "setmealCache",allEntries = true)
public Result delete(@RequestParam List<Long> ids){//让Spring自动处理字符串变成集合
log.info("批量删除套餐:{}",ids);
setmealService.deleteBatch(ids);
return Result.success();
}
/**
* 修改套餐
* @param setmealDTO
* @return
*/
@PutMapping
@ApiOperation("修改套餐")
@CacheEvict(cacheNames = "setmealCache",allEntries = true)
public Result update(@RequestBody SetmealDTO setmealDTO){
log.info("修改套餐信息:{}",setmealDTO);
setmealService.update(setmealDTO);
return Result.success();
}
/**
* 套餐起售停售
* @param status
* @param id
* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("套餐起售停售")
@CacheEvict(cacheNames = "setmealCache",allEntries = true)
public Result startOrStop(@PathVariable Integer status, Long id) {
setmealService.startOrStop(status, id);
return Result.success();
}
}