Day70(7)-F:\硕士阶段\Java\课程资料\1、黑马程序员Java项目《苍穹外卖》企业级开发实战\sky-take-out-缓存redis

苍穹外卖

缓存菜品

image-20251226142251860

image-20251226142453817

image-20251226142900251

技术栈:

  1. 设置新的jwt锁并注入
  2. 调用redis层增删改查
  3. 缓存数据需要及时清理,避免数据不一致(菜品修改操作,菜品删除操作,起售或停售,菜品新增操作)抽取成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行)

image-20251227094111622

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

类似于事务管理

image-20251227120409971

image-20251227120433489

技术栈

  1. 开启注解缓存功能,在启动类上
  2. 在controller层的方法上添加对应对应@CachePut注解,涉及springEL语法
  3. 在controller层的方法上添加对应对应@Cacheable注解,涉及springEL语法
  4. 在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();
   }

缓存套餐

image-20251227141221646

技术栈:

  1. 启动类上开启缓存注解功能
  2. user包controller下的list方法加入@Cacheable
  3. 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();
}

添加购物车

image-20251227150107843

image-20251227150131278

image-20251227150403266

image-20251227150453007

image-20251227150839201

技术栈

  1. 冗余字段空间换时间
  2. 添加购物车,需做多重判断
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);
}

查看购物车

image-20251227165411781

查看购物车-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;
}

清空购物车

image-20251227171141909

/**
 * 清空购物车
 * @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);
posted @ 2025-12-28 16:54  David大胃  阅读(4)  评论(0)    收藏  举报