文章目录
缓存菜品
问题说明
用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户访问量比较大,数据库访问压力随之增大。
结果:系统响应慢,用户体验差
实现思路
通过Redis来缓存菜品数据,减少数据库查询操作
缓存逻辑分析:
- 每个分类下的菜品保存一份缓存数据
- 数据库中菜品数据有变更时清理缓存数据
- 数据一致性
保证mysql数据与redis缓存数据一致性的解决方案
- 增量同步,数据库增删改什么,redis缓存就增删改什么,实稍微复杂,针对不同的情况处理
- 全量同步,将redis的数据删掉,重新将mysql数据写入到缓存(redis推荐这个,比较简单,内存操作很快,性能没什么影响)
- 实现步骤:商家执行增删改操作,删除redis数据,下次查询就会重新写入
- 实现步骤:商家执行增删改操作,删除redis数据,下次查询就会重新写入
代码开发
查询缓存实现
@ApiOperation("根据分类id查询菜品")
@GetMapping("/list")
public Result<List<DishVO>> findByCategoryId(Long categoryId){
log.info("根据分类id查询菜品:{}",categoryId);
//1.构造redis缓存key
String key = "dish_" + categoryId;
//2、使用redisTemplate查询缓存这个key数据,返回List<DishVO>
List<DishVO> dishVOList = (List<DishVO>) redisTemplate.opsForValue().get(key);
//3.判断dishVOList是否为null
if (dishVOList == null){
Dish dish = new Dish();
dish.setCategoryId(categoryId);
dish.setStatus(StatusConstant.ENABLE);
dishVOList = dishService.findByCategoryIdOnUser(dish);
//写入缓存
if (dishVOList != null && dishVOList.size() > 0){
redisTemplate.opsForValue().set(key,dishVOList);
}
}
return Result.success(dishVOList);
}
增删改保证mysql和redis的数据一致
缓存套餐
Spring Cache
Spring Cache是一个框架,实现了基于注解的缓存功能,只需要一个简单地加一个注解,就能实现缓存功能。
Spring Cache 提供了一层抽象,底层可以切换不同的缓存实现,例如:
- EHCache
- Caffeine
- Redis
依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>2.7.3</version>
</dependency>
常用注解:
- @EnableCaching:开启SpringCache注解扫描
- @Cacheable:首先会查询缓存是否有数据,如果有直接返回,如果没有执行方法并且将方法返回值写入缓存,缺点:默认执行方法返回值为null,会缓存,导致缓存的数据为null;解决办法:unless,进行条件判断,作用是条件不成立写入缓存;#result是获取方法的返回值对象condition(了解即可),条件成立才写入缓存,但是这个不可以使用#result,无法获取返回值
- @CachePut:将方法返回值写入缓存; value:设置缓存名称,一个缓存名称相当于一个分类,这个缓存名称下可以有多个key key: 设置缓存的key 例如: value=“userCache” key=“#user.id” 生成缓存的格式 userCache::1
- @CacheEvict: 删除指定的key数据 key:删除指定id的缓存 allEntries:删除所有以userCache前缀的缓存
实现思路
具体的实现思路如下:
- 导入Spring Cache和Redis相关maven坐标
- 在启动类上加入@EnableCaching注解,开启缓存注解功能
- 在用户端接口SetmealController的list方法上加入@Cacheable注解
- 在管理端接口SetmealController的 save、delete、update、startOrStop等方法上加入@CacheEvict注解
添加购物车
需求分析和设计
生活中的购物车:用于暂时存放所选商品的一种手推车
接口设计:
数据库设计表:
代码开发
如果添加购物车存在的菜品或套餐,只需要在数量上+1,如果不存在,则添加对应的菜品和套餐。
@Override
public void insertShopCart(ShoppingCartDTO shoppingCartDTO) {
ShoppingCart shoppingCart = new ShoppingCart();
BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);
//查询自己的购物车数据
shoppingCart.setUserId(BaseContext.getCurrentId());
//判断当前商品是否在购物车中
List<ShoppingCart> shoppingCartList = shoppingCartMapper.list(shoppingCart);
if (shoppingCartList != null && shoppingCartList.size() == 1){
//如果已存在,就更新数量,数量加1
shoppingCart = shoppingCartList.get(0);
shoppingCart.setNumber(shoppingCart.getNumber() + 1);
ShoppingCartMapper.updateNumberById(shoppingCart);
}else {
//如果不存在,插入数据,数量就是1
Long dishId = shoppingCart.getDishId();
if (dishId != null){
//添加到购物车的是菜品
DishVO dishVO = dishMapper.findById(dishId);
shoppingCart.setName(dishVO.getName());
shoppingCart.setImage(dishVO.getImage());
shoppingCart.setAmount(dishVO.getPrice());
}else {
//添加到购物车的是套餐
SetmealVO setmealVO = setMealMapper.findById(shoppingCart.getSetmealId());
shoppingCart.setName(setmealVO.getName());
shoppingCart.setImage(setmealVO.getImage());
shoppingCart.setAmount(setmealVO.getPrice());
}
shoppingCart.setNumber(1);
shoppingCart.setCreateTime(LocalDateTime.now());
shoppingCartMapper.insert(shoppingCart);
}
}
查看购物车
需求分析和设计
接口设计
代码开发
@Override
public List<ShoppingCart> list() {
ShoppingCart shoppingCart = ShoppingCart.builder().userId(BaseContext.getCurrentId()).build();
return shoppingCartMapper.list(shoppingCart);
}
清空购物车
需求分析和设计
接口设计
代码开发
@Override
public void deleteAll() {
shoppingCartMapper.deleteAll(BaseContext.getCurrentId());
}