Day70(7)-F:\硕士阶段\Java\课程资料\1、黑马程序员Java项目《苍穹外卖》企业级开发实战\sky-take-out-缓存redis
苍穹外卖
缓存菜品
技术栈:
- 设置新的jwt锁并注入
- 调用redis层增删改查
- 缓存数据需要及时清理,避免数据不一致(菜品修改操作,菜品删除操作,起售或停售,菜品新增操作)抽取成AOP或者定义一个私有方法
1.设置新的jwt锁并注入
package com.sky.controller.user;
import com.sky.constant.JwtClaimsConstant;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.User;
import com.sky.properties.JwtProperties;
import com.sky.result.Result;
import com.sky.service.UserService;
import com.sky.utils.JwtUtil;
import com.sky.vo.UserLoginVO;
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;
import java.util.HashMap;
@RestController
@RequestMapping("/user/user")
@Api(tags = "C端用户模块")
@Slf4j
public class UserController {
@Autowired
private UserService userService;
@Autowired
private JwtProperties jwtProperties;
@PostMapping("/login")
@ApiOperation("微信登录")
public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO){
log.info("微信用户登录:{}",userLoginDTO.getCode());
//微信登录
User user = userService.wxlogin(userLoginDTO);
//为微信用户生成jwt令牌
HashMap<String, Object> claims = new HashMap<>();
claims.put(JwtClaimsConstant.USER_ID,user.getId());
String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);
UserLoginVO userLoginVO = UserLoginVO.builder()
.id(user.getId())
.openid(user.getOpenid())
.token(token)
.build();
return Result.success(userLoginVO);
}
}
package com.sky.interceptor;
import com.sky.constant.JwtClaimsConstant;
import com.sky.context.BaseContext;
import com.sky.properties.JwtProperties;
import com.sky.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* jwt令牌校验的拦截器
*/
@Component
@Slf4j
public class JwtTokenUserInterceptor implements HandlerInterceptor {
@Autowired
private JwtProperties jwtProperties;
/**
* 校验jwt
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("当前线程的id:"+Thread.currentThread().getId());
//判断当前拦截到的是Controller的方法还是其他资源
if (!(handler instanceof HandlerMethod)) {
//当前拦截到的不是动态方法,直接放行
return true;
}
//1、从请求头中获取令牌
String token = request.getHeader(jwtProperties.getUserTokenName());
//2、校验令牌
try {
log.info("jwt校验:{}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
log.info("当前用户id:", userId);
BaseContext.setCurrentId(userId);
//3、通过,放行
return true;
} catch (Exception ex) {
//4、不通过,响应401状态码
log.error("JWT解析发生极其严重的错误!!原因:{}", ex.getMessage());
ex.printStackTrace(); // 这行非常重要,它会告诉你到底是密钥错了还是过期了
response.setStatus(401);
return false;
}
}
}
package com.sky.config;
import com.sky.interceptor.JwtTokenAdminInterceptor;
import com.sky.interceptor.JwtTokenUserInterceptor;
import com.sky.json.JacksonObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.List;
/**
* 配置类,注册web层相关组件
*/
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Autowired
private JwtTokenAdminInterceptor jwtTokenAdminInterceptor;
@Autowired
private JwtTokenUserInterceptor jwtTokenUserInterceptor;
/**
* 注册自定义拦截器
*
* @param registry
*/
protected void addInterceptors(InterceptorRegistry registry) {
log.info("开始注册自定义拦截器...");
registry.addInterceptor(jwtTokenAdminInterceptor)
.addPathPatterns("/admin/**")
.excludePathPatterns("/admin/employee/login");
registry.addInterceptor(jwtTokenUserInterceptor)
.addPathPatterns("/user/**")
.excludePathPatterns("/user/user/login")
.excludePathPatterns("/user/shop/status");
}
2.调用redis层增删改查
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 javax.annotation.Resource;
import java.util.List;
@RestController("userDishController")
@RequestMapping("/user/dish")
@Slf4j
@Api(tags = "C端-菜品浏览接口")
public class DishController {
@Autowired
private DishService dishService;
@Autowired
private RedisTemplate<String,Object> 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){
log.info("数据库查询结果不为空,长度为:{}", list.size());
//如果存在,直接返回,无需查询数据库
return Result.success(list);
}else {
log.error("数据库查询结果为 NULL!");
}
log.info("根据分类id查询菜品");
Dish dish = new Dish();
dish.setCategoryId(categoryId);
dish.setStatus(StatusConstant.ENABLE);
//如果不存在,查询数据库并将查询到的数据放入redis中
list = dishService.listWithFlavor(dish);
redisTemplate.opsForValue().set("test_key", "hello_redis");
log.info("查询到的菜品列表大小: {}", (list == null ? "null" : list.size()));
redisTemplate.opsForValue().set(key,list);
log.info("Redis 存储指令已发出,Key 为: {}", key);
return Result.success(list);
}
}
3.缓存数据需要及时清理,避免数据不一致(菜品修改操作,菜品删除操作,起售或停售,菜品新增操作),抽取成AOP或者定义一个私有方法(147-154行)
package com.sky.controller.admin;
import com.sky.constant.StatusConstant;
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.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
/**
* 菜品管理
*/
@RestController
@RequestMapping("/admin/dish")
@Slf4j
@Api(tags = "菜品相关接口")
public class DishController {
@Autowired
private DishService dishService;
@Autowired
private RedisTemplate<String,Object> redisTemplate;
/**
* 新增菜品
* @param dishDTO
* @return
*/
@PostMapping
@ApiOperation("新增菜品")
public Result save(@RequestBody DishDTO dishDTO){
log.info("新增菜品:{}",dishDTO);
dishService.saveWithFlavor(dishDTO);
//将所有的菜品缓存数据清理掉,所以的dish_开头的key(先查)
// Set<String> keys = redisTemplate.keys("dish_*");
// redisTemplate.delete(keys);
String key = "dish" + dishDTO.getCategoryId();
cleanCache(key);
return Result.success();
}
/**
* 菜品分页查询
* @param dishPageQueryDTO
* @return
*/
@GetMapping("/page")
@ApiOperation("菜品分页查询")
public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO){
log.info("菜品分页查询");
PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);
return Result.success(pageResult);
}
/**
* 菜品的批量删除
* @param ids
* @return
*/
@DeleteMapping
@ApiOperation("菜品的批量删除")
public Result delete(@RequestParam List<Long> ids){
//这里 @RequestParam 的作用就是将前端传来的字符串(如 1,2,3)或多个同名参数解析并填充到 List<Long> 集合中。
log.info("菜品批量删除:{}",ids);
dishService.deleteBatch(ids);
//将所有的菜品缓存数据清理掉,所以的dish_开头的key(先查)
// Set<String> keys = redisTemplate.keys("dish_*");
// redisTemplate.delete(keys);
cleanCache("dish*");
return Result.success();
}
/**
* 根据id查询菜品
* @param id
* @return
*/
@ApiOperation("根据id查询菜品")
@GetMapping("/{id}")
public Result<DishVO> getById(@PathVariable long id){
log.info("根据id查询菜品:{}",id);
DishVO dishVO = dishService.getByIdWithFlavor(id);
return Result.success(dishVO);
}
/**
* 根据id修改菜品基本信息和对应的口味信息
* @param dishDTO
* @return
*/
@PutMapping
@ApiOperation("修改菜品")
public Result update(@RequestBody DishDTO dishDTO){
log.info("修改菜品:{}",dishDTO);
dishService.updateWithFlavor(dishDTO);
//将所有的菜品缓存数据清理掉,所以的dish_开头的key(先查)
// Set<String> keys = redisTemplate.keys("dish_*");
// redisTemplate.delete(keys);
cleanCache("dish*");
return Result.success();
}
@PostMapping("/status/{status}")
@ApiOperation("菜品的起售停售")
public Result<String> startOrStop(@PathVariable Integer status,Long id){
dishService.startOrStop(status,id);
//将所有的菜品缓存数据清理掉,所以的dish_开头的key(先查)
// Set<String> keys = redisTemplate.keys("dish_*");
// redisTemplate.delete(keys);
cleanCache("dish*");
return Result.success();
}
/**
* 根据分类id查询菜品
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<Dish>> getByCateGoryId(Long categoryId){
List<Dish> list = dishService.list(categoryId);
return Result.success(list);
}
/**
* 清理缓存数据
* @param patten
*/
private void cleanCache(String patten){
Set<String> keys = redisTemplate.keys(patten);
redisTemplate.delete(keys);
}
}
Spring Cache
类似于事务管理
技术栈
- 开启注解缓存功能,在启动类上
- 在controller层的方法上添加对应对应@CachePut注解,涉及springEL语法
- 在controller层的方法上添加对应对应@Cacheable注解,涉及springEL语法
- 在controller层的方法上添加对应对应@CacheEvict注解,涉及springEL语法
1. 开启注解缓存功能,在启动类上(第10行)
package com.itheima;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@Slf4j
@SpringBootApplication
@EnableCaching//开启注解缓存功能
public class CacheDemoApplication {
public static void main(String[] args) {
SpringApplication.run(CacheDemoApplication.class,args);
log.info("项目启动成功...");
}
}
2.在controller层的方法上添加对应@CachePut注解,涉及springEL语法
存到缓存redis中的key为cacheNames加上两个冒号,再加上key对应的值,通过#user可以取到传入参数user的对应数据,所以需要命名和传入参数保持一致;或者也可以通过#result
,也就是取到方法返回值;或者通过#p0.id,传入的参数,第一个是p0或ao或#root.args[0].id。
由于插入redis形如userCache::1;会在redis中生成树状数据,中间层是Empty;有:就换层
但是实际上redis中都是平级存储的,只是展示为树状
@PostMapping
@CachePut(cacheNames = "userCache",key = "#user.id")//如果使用springcache缓存数据,key的生成:userCache::1
//@CachePut(cacheNames = "userCache",key = "#result.id")
//@CachePut(cacheNames = "userCache",key = "#p0.id")
//@CachePut(cacheNames = "userCache",key = "#a0.id")
//@CachePut(cacheNames = "userCache",key = "#root.args[0].id")
public User save(@RequestBody User user){
userMapper.insert(user);
return user;
}
3.在controller层的方法上添加对应对应@Cacheable注解,涉及springEL语法
springcache底层基于代理技术,为当前controller创建一个代理对象,请求之前会先进入代理对象,在代理对象里面查询redis,先查redis,没有再sql,执行完sql返回后才更新redis
@GetMapping
@Cacheable(cacheNames = "userCache",key = "#id")//key的生成:userCache::2
public User getById(Long id){
User user = userMapper.getById(id);
return user;
}
4.在controller层的方法上添加对应对应@CacheEvict注解,涉及springEL语法
也是基于代理对象,controller执行完才删除redis数据
@DeleteMapping
@CacheEvict(cacheNames = "userCache",key = "#id")//key的生成:userCache::2
public void deleteById(Long id){
userMapper.deleteById(id);
}
如果不是唯一删除,key不止一个
@DeleteMapping("/delAll")
@CacheEvict(cacheNames = "userCache",allEntries = true)
public void deleteAll(){
userMapper.deleteAll();
}
缓存套餐
技术栈:
- 启动类上开启缓存注解功能
- user包controller下的list方法加入@Cacheable
- admin包controller下的list方法加入@CacheEvict
1.启动类上开启缓存注解功能
package com.sky;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@Slf4j
@EnableCaching
public class SkyApplication {
public static void main(String[] args) {
SpringApplication.run(SkyApplication.class, args);
log.info("server started");
}
}
2.user包controller下的list方法加入@Cacheable
/**
* 条件查询
*
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询套餐")
@Cacheable(cacheNames = "setmealCache",key = "#categoryId")//key:setmealCache::100
public Result<List<Setmeal>> list(Long categoryId) {
Setmeal setmeal = new Setmeal();
setmeal.setCategoryId(categoryId);
setmeal.setStatus(StatusConstant.ENABLE);
List<Setmeal> list = setmealService.list(setmeal);
return Result.success(list);
}
3.admin包controller下的list方法加入@CacheEvict
新增套餐后,比如人气套餐本来有3个,新增了一个,缓存里面实际上还是保存了三个,但是数据库已经有四个了,此时需要把缓存里面的人气套餐分类删掉。
/**
* 新增套餐
* @param setmealDTO
* @return
*/
@ApiOperation("新增套餐")
@PostMapping
@CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId")
//新增套餐导致“该套餐分类id”下所有套餐与数据库不一致,例如缓存里3个套餐,数据库4个,所有需要清除缓存中“这一个分类id”下的所有套餐,用户查询时重新从数据库获取最新的数据
public Result save(@RequestBody SetmealDTO setmealDTO){
log.info("新增套餐:{}",setmealDTO);
setmealService.saveWithCategoryId(setmealDTO);
return Result.success();
}
如果传入的是数组,且需要批量删除缓存,使用allEntries = true
/**
* 根据ids删除套餐
* @param ids
* @return
*/
@DeleteMapping
@ApiOperation("根据ids删除套餐")
@CacheEvict(cacheNames = "setmealCache",allEntries = true)
public Result delete(@RequestParam List<Long> ids){
log.info("根据ids删除套餐:{}",ids);
setmealService.deleteById(ids);
return Result.success();
}
/**
* 根据id修改套餐
* @param setmealDTO
* @return
*/
@ApiOperation("根据id修改套餐")
@PutMapping
@CacheEvict(cacheNames = "setmealCache",allEntries = true)
public Result update(@RequestBody SetmealDTO setmealDTO){
log.info("根据id修改套餐:{}",setmealDTO);
setmealService.update(setmealDTO);
return Result.success();
}
/**
* 根据id修改套餐状态
* @param status
* @param id
* @return
*/
@ApiOperation("根据id修改套餐状态")
@PostMapping("/status/{status}")
@CacheEvict(cacheNames = "setmealCache",allEntries = true)
public Result updateStatus(@PathVariable Integer status,long id){
log.info("根据id修改套餐{}状态:{}",id,status);
setmealService.updateStatus(status,id);
return Result.success();
}
添加购物车
技术栈
- 冗余字段空间换时间
- 添加购物车,需做多重判断
2.添加购物车,需做多重判断
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 = "购物车相关接口")
public class ShoppingCartController {
@Autowired
private ShoppingCartService shoppingCartService;
/**
* 添加购物车
* @return
*/
@PostMapping("/add")
@ApiOperation("添加购物车")
public Result add(@RequestBody ShoppingCartDTO shoppingCartDTO){
log.info("添加购物车,商品信息为:{}",shoppingCartDTO);
shoppingCartService.addShoppingCart(shoppingCartDTO);
return Result.success();
}
}
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 com.sky.vo.SetmealVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
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
@Transactional
public void addShoppingCart(ShoppingCartDTO shoppingCartDTO) {
//判断当前加入购物车中的商品是否已经存在
ShoppingCart shoppingCart = new ShoppingCart();
BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);
//DTO里面没有用户id,所以要获取
Long userId = BaseContext.getCurrentId();
shoppingCart.setUserId(userId);
List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
//list结果只有可能是查不到或者查到一条结果
if (list!=null && list.size() > 0){
//如果已经存在,只需要将数量加一
ShoppingCart cart = list.get(0);
cart.setNumber(cart.getNumber()+1);
shoppingCartMapper.updateNumberById(cart);
}else {
//如果不存在,插入一条购物车数据
//判断本次添加到购物车的是菜品还是套餐
Long dishId = shoppingCartDTO.getDishId();
if (dishId != null){
//本次添加到购物车的为菜品
Dish dish = dishMapper.getById(dishId);
shoppingCart.setName(dish.getName());
shoppingCart.setImage(dish.getImage());
shoppingCart.setAmount(dish.getPrice());
}else {
//本次添加到购物车的是套餐
Long setmealId = shoppingCartDTO.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);
}
}
}
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 cart
*/
@Update("update shopping_cart set number = #{number} where id = #{id}")
void updateNumberById(ShoppingCart cart);
/**
* 插入购物车数据
* @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);
}
查看购物车
查看购物车-controller类
/**
* 查看购物车
* @return
*/
@ApiOperation("查看购物车")
@GetMapping("/list")
public Result<List<ShoppingCart>> list(){
List<ShoppingCart> list = shoppingCartService.showShoppingCart();
return Result.success(list);
}
查看购物车-serviceimpl类
/**
* 查看购物车
* @return
*/
@Override
public List<ShoppingCart> showShoppingCart() {
//获取到当前用户微信id
Long userId = BaseContext.getCurrentId();
ShoppingCart shoppingCart = ShoppingCart.builder()
.userId(userId)
.build();
List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
return list;
}
清空购物车
/**
* 清空购物车
* @return
*/
@DeleteMapping("/clean")
@ApiOperation("清空购物车")
public Result clean(){
shoppingCartService.cleanShoppingCart();
return Result.success();
}
@PostMapping("/sub")
@ApiOperation("删除购物车中的一个商品")
public Result sub(@RequestBody ShoppingCartDTO shoppingCartDTO){
shoppingCartService.subShoppingCart(shoppingCartDTO);
return Result.success();
}
/**
* 清空购物车
*/
@Override
public void cleanShoppingCart() {
//获取到当前用户微信id
Long userId = BaseContext.getCurrentId();
shoppingCartMapper.deleteByUserId(userId);
}
/**
* 删除购物车
* @param shoppingCartDTO
*/
@Override
public void subShoppingCart(ShoppingCartDTO shoppingCartDTO) {
//先根据id查询购物车里面的数量
ShoppingCart shoppingCart = new ShoppingCart();
BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);
//DTO里面没有用户id,所以要获取
Long userId = BaseContext.getCurrentId();
shoppingCart.setUserId(userId);
List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
if (list !=null&&list.size() >0){
ShoppingCart cart = list.get(0);
if (cart.getNumber() ==1){
shoppingCartMapper.deleteById(cart);
}else {
cart.setNumber(cart.getNumber()-1);
shoppingCartMapper.updateNumberById(cart);
}
// //校验这个商品或者套餐的数量
// Integer number = cart.getNumber();
// //先把数量减一
// cart.setNumber(number-1);
// shoppingCartMapper.updateNumberById(cart);
// if (cart.getNumber() == 0){
// //需要删除在数据库里面对应数据
// shoppingCartMapper.deleteById(cart);
}
/**
* 根据userId删除购物车
* @param userId
*/
@Delete("delete from shopping_cart where user_id = #{userId}")
void deleteByUserId(Long userId);
/**
* 删除购物车
* @param cart
*/
@Delete("delete from shopping_cart where id = #{id}")
void deleteById(ShoppingCart cart);

浙公网安备 33010602011771号