苍穹外卖项目学习日记(10) day07
缓存菜品
- 更改controll层,改为先查询redis中是否有相关数据
- user-DishController.java
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<DishVO>> list(Long categoryId) {
String key = "dist_" + categoryId;
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);
redisTemplate.opsForValue().set(key,list);
return Result.success(list);
}
- 上述代码存在以下问题,无法保证缓存和数据库数据的一致性,修改代码如下(在新增、修改、删除、起售停售菜品时进行清理缓存操作)
- admin-DishController.java
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
@RequestMapping("/admin/dish")
@Api(tags = "菜品相关接口")
@Slf4j
public class DishController {
@Autowired
private DishService dishService;
@Autowired
private RedisTemplate redisTemplate;
/**
* 新增菜品
* @param dishDTO
* @return
*/
@PostMapping
@ApiOperation("新增菜品")
public Result save(@RequestBody DishDTO dishDTO){
log.info("新增菜品:{}",dishDTO);
dishService.saveWithFlavor(dishDTO);
String key = "dish_" + dishDTO.getCategoryId();
cleanCache(key);
return Result.success();
}
/**
* 菜品分页查询
* @param dto
* @return
*/
@GetMapping("/page")
@ApiOperation("菜品分页查询")
public Result<PageResult> page(DishPageQueryDTO dto){
log.info("菜品分页查询:{}",dto);
PageResult pageResult = dishService.pageQuery(dto);
return Result.success(pageResult);
}
/**
* 菜品批量删除
* @param ids
* @return
*/
@DeleteMapping
@ApiOperation("菜品批量删除")
public Result delete(@RequestParam List<Long> ids){
log.info("菜品批量删除:{}",ids);
dishService.deleteBatch(ids);
cleanCache("dish_*");
return Result.success();
}
/**
* 根据id查询菜品
* @param id
* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据id查询菜品")
public Result<DishVO> getById(@PathVariable Long id){
log.info("根据id查询菜品:{}",id);
DishVO dishVO = dishService.getByIdWithFlavor(id);
return Result.success(dishVO);
}
/**
* 修改菜品
* @param dishDTO
* @return
*/
@PutMapping
@ApiOperation("修改菜品")
public Result update(@RequestBody DishDTO dishDTO){
log.info("修改菜品:{}",dishDTO);
dishService.updateWithFlavor(dishDTO);
cleanCache("dish_*");
return Result.success();
}
/**
* 根据分类ID查询菜品
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类ID查询菜品")
public Result<List<Dish>> getByCategoryId(Long categoryId){
log.info("根据分类ID查询菜品:{}",categoryId);
List<Dish> dishes = dishService.getByCategoryId(categoryId);
return Result.success(dishes);
}
/**
* 修改菜品销售状态
* @param status
* @param id
* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("修改菜品销售状态")
public Result startOrStop(@PathVariable Integer status,Long id){
log.info("修改菜品销售状态:{},{}",status,id);
dishService.startOrStop(status,id);
cleanCache("dish_*");
return Result.success();
}
private void cleanCache(String pattern){
Set keys = redisTemplate.keys(pattern);
redisTemplate.delete(keys);
}
}
缓存套餐
-
spring cache常用注解
-
cachePut注解中,
@CachePut(cacheNames="",key="")
,存入缓存的key值为cacheNames::key,其中key可以动态获取参数,也可以动态获取返回值。通过spel语法即可。ex:key = "#user.id",key = "#result.id",key = "#p0.id/a0.id"
,user为形参,result为返回值,p0/a0为第一个参数,所以p1为第二个,以此类推,获取root.args[0]。 -
启动类添加
@EnableCaching
注解 -
user文件夹下SeatmealController.java中给list方法添加相关注解,
@Cacheable(cacheNames = "setmealCache",key = "#categoryId")
-
在admin文件夹下SeatmealController.java,给save方法添加注解,
@CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId")
,给delete、update、startOrStop方法添加注解@CacheEvict(cacheNames = "setmealCache",allEntries = true)
添加购物车
- 在controller层user目录下创建ShoppingCartController类,并添加加入购物车方法
- ShoppingCartController.java
package com.sky.controller.user;
import com.sky.dto.ShoppingCartDTO;
import com.sky.result.Result;
import com.sky.service.ShoppingCartService;
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.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user/shoppingCart")
@Slf4j
@Api(tags = "C端购物车相关接口")
public class ShoppingCartController {
@Autowired
private ShoppingCartService shoppingCartService;
/**
* 添加购物车
* @param shoppingCartDTO
* @return
*/
@PostMapping("/add")
@ApiOperation("添加购物车")
public Result add(@RequestBody ShoppingCartDTO shoppingCartDTO){
log.info("添加购物车:{}",shoppingCartDTO);
shoppingCartService.addShoppingCart(shoppingCartDTO);
return Result.success();
}
}
- 创建ShoppingCartService类,并在实现类中实现
- ShoppingCartServiceImpl.java
package com.sky.service.impl;
import com.sky.context.BaseContext;
import com.sky.dto.ShoppingCartDTO;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.ShoppingCart;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.service.ShoppingCartService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
@Service
@Slf4j
public class ShoppingCartServiceImpl implements ShoppingCartService {
@Autowired
private ShoppingCartMapper shoppingCartMapper;
@Autowired
private DishMapper dishMapper;
@Autowired
private SetmealMapper setmealMapper;
/**
* 添加购物车
* @param shoppingCartDTO
*/
@Override
public void addShoppingCart(ShoppingCartDTO shoppingCartDTO) {
//判断当前商品在数据库中是否已经存在
ShoppingCart shoppingCart = new ShoppingCart();
BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);
Long currentId = BaseContext.getCurrentId();
shoppingCart.setUserId(currentId);
List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
//若存在,将数量加一
if (list != null && list.size() > 0){
ShoppingCart cart = list.get(0);
cart.setNumber(cart.getNumber() + 1);
shoppingCartMapper.updateNumberById(cart);
}else {
//不存在,就插入一条数据
//判断是菜品还是套餐
Long dishId = shoppingCart.getDishId();
if(dishId !=null){
Dish dish = dishMapper.getById(dishId);
shoppingCart.setName(dish.getName());
shoppingCart.setImage(dish.getImage());
shoppingCart.setAmount(dish.getPrice());
}else{
Long setmealId = shoppingCart.getSetmealId();
Setmeal setmeal = setmealMapper.getById(setmealId);
shoppingCart.setName(setmeal.getName());
shoppingCart.setImage(setmeal.getImage());
shoppingCart.setAmount(setmeal.getPrice());
}
shoppingCart.setNumber(1);
shoppingCart.setCreateTime(LocalDateTime.now());
shoppingCartMapper.insert(shoppingCart);
}
}
}
- 创建ShoppingCartMapper类,添加相应方法
- ShoppingCartMapper.java
package com.sky.mapper;
import com.sky.entity.ShoppingCart;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Update;
import java.util.List;
@Mapper
public interface ShoppingCartMapper {
/**
* 动态条件查询
* @param shoppingCart
* @return
*/
List<ShoppingCart> list(ShoppingCart shoppingCart);
/**
* 根据id修改商品数量
* @param shoppingCart
*/
@Update("update shopping_cart set number = #{number} where id = #{id}")
void updateNumberById(ShoppingCart shoppingCart);
/**
* 插入数据
* @param shoppingCart
*/
@Insert("insert into shopping_cart(name, image, user_id, dish_id, setmeal_id, dish_flavor, number, amount, create_time) " +
"values (#{name},#{image},#{userId},#{dishId},#{setmealId},#{dishFlavor},#{number},#{amount},#{createTime})")
void insert(ShoppingCart shoppingCart);
}
- ShoppingCartMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.ShoppingCartMapper">
<select id="list" resultType="com.sky.entity.ShoppingCart">
select * from shopping_cart
<where>
<if test="userId != null">
and user_id = #{userId}
</if>
<if test="setmealId != null">
and setmeal_id = #{setmealId}
</if>
<if test="dishId != null">
and dish_id = #{dishId}
</if>
<if test="dishFlavor != null">
and dish_flavor = #{dishFlavor}
</if>
</where>
</select>
</mapper>
查看购物车
- 在user目录下controller层的ShoppingCartController类,添加查看购物车方法
- ShoppingCartController.java
@GetMapping("/list")
@ApiOperation("查看购物车")
public Result<List<ShoppingCart>> list(){
List<ShoppingCart> list = shoppingCartService.showShoppingCart();
return Result.success(list);
}
- 在ShoppingCartServiceImpl类中实现
- ShoppingCartServiceImpl.java
public List<ShoppingCart> showShoppingCart() {
Long currentId = BaseContext.getCurrentId();
ShoppingCart shoppingCart = ShoppingCart.builder()
.userId(currentId)
.build();
List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
return list;
}
清空购物车
- 在user目录下controller层的ShoppingCartController类,添加清空购物车方法
- ShoppingCartController.java
@DeleteMapping("/clean")
@ApiOperation("清空购物车")
public Result clean(){
shoppingCartService.cleanShoppingCart();
return Result.success();
}
- 在ShoppingCartServiceImpl类中实现
- ShoppingCartServiceImpl.java
@Override
public void cleanShoppingCart() {
Long currentId = BaseContext.getCurrentId();
shoppingCartMapper.deleteByUserId(currentId);
}
- ShoppingCartMapper类中添加相应方法
- ShoppingCartMapper.java
@Delete("delete from shopping_cart where user_id = #{userId}")
void deleteByUserId(Long userId);