苍穹外卖【day7| 对购物车进行操作】

🌈个人主页:一条泥憨鱼(欢迎各位大佬莅临)

🎬精选专栏传送门:

❄️《数据结构》 ❄️《AI与Agent那些事》

❄️《从0开始学计算机网络》 ❄️《后端开发》

添加购物车

需求分析和设计

数据库设计

代码开发

1️⃣ 数据传输层 (DTO)

ShoppingCartDTO.java

java 复制代码
@Data
public class ShoppingCartDTO implements Serializable {
    private Long dishId;        // 菜品ID
    private Long setmealId;     // 套餐ID
    private String dishFlavor;  // 菜品口味
}

作用:接收前端传来的添加购物车请求数据,只包含必要的前端参数。

2️⃣ 实体类 (Entity)

ShoppingCart.java

java 复制代码
@Data
@Builder
public class ShoppingCart implements Serializable {
    private Long id;
    private String name;        // 商品名称
    private Long userId;        // 用户ID
    private Long dishId;        // 菜品ID
    private Long setmealId;     // 套餐ID
    private String dishFlavor;  // 口味
    private Integer number;     // 数量
    private BigDecimal amount;  // 金额
    private String image;       // 图片
    private LocalDateTime createTime; // 创建时间
}

作用:购物车的完整数据模型,对应数据库表结构。

3️⃣ 控制层 (Controller)

ShoppingCartController.java

java 复制代码
@RestController
@RequestMapping("/user/shoppingCart")
@Api(tags = "C端购物车相关接口")
public class ShoppingCartController {
    
    @Autowired
    private ShoppingCartService shoppingCartService;

    @PostMapping("/add")
    @ApiOperation("添加购物车")
    public Result add(@RequestBody ShoppingCartDTO shoppingCartDTO){
        log.info("添加购物车,商品信息为:{}", shoppingCartDTO);
        shoppingCartService.addShoppingCart(shoppingCartDTO);
        return Result.success();
    }
}
  • 路由POST /user/shoppingCart/add
  • 功能:接收JSON请求,调用service层处理,返回成功结果
  • 使用 @Slf4j:启用Lombok日志

4️⃣ 服务接口层 (Service Interface)

ShoppingCartService.java

java 复制代码
public interface ShoppingCartService {
    void addShoppingCart(ShoppingCartDTO shoppingCartDTO);
}

5️⃣ 服务实现层 (Service Implementation)

ShoppingCartServiceImpl.java

java 复制代码
@Service
@Slf4j
public class ShoppingCartServiceImpl implements ShoppingCartService {
    
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    
    @Autowired
    private DishMapper dishMapper;
    
    @Autowired
    private SetmealMapper setmealMapper;

    public void addShoppingCart(ShoppingCartDTO shoppingCartDTO){
        // 1. 构建查询条件
        ShoppingCart shoppingCart = new ShoppingCart();
        BeanUtils.copyProperties(shoppingCartDTO, shoppingCart);
        Long userId = BaseContext.getCurrentId();  // 获取当前登录用户ID
        shoppingCart.setUserId(userId);

        // 2. 查询当前用户的购物车中是否已有该商品
        List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
        
        // 3. 如果存在该商品,数量+1
        if(list != null && list.size() > 0){
            ShoppingCart cart = list.get(0);
            cart.setNumber(cart.getNumber() + 1);
            shoppingCartMapper.updateNumberById(cart);
        } 
        // 4. 如果不存在,需要新增一条记录
        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);
        }
    }
}

核心业务逻辑

  1. 用户隔离 :通过 BaseContext.getCurrentId() 获取当前用户ID,确保每个用户只能操作自己的购物车
  2. 存在性检查:先查询购物车是否已存在相同商品(判断条件:userId + dishId/setmealId + dishFlavor)
  3. 数量累加 :如果已存在,只需将数量 number + 1
  4. 新增记录:如果不存在,根据 dishId 或 setmealId 查询商品信息,插入新记录

6️⃣ 数据访问层 (Mapper)

ShoppingCartMapper.java

java 复制代码
@Mapper
public interface ShoppingCartMapper {
    // 动态条件查询
    List<ShoppingCart> list(ShoppingCart shoppingCart);
    
    // 根据id修改商品数量
    @Update("update shopping_cart set number = #{number} where id = #{id}")
    void updateNumberById(ShoppingCart 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);
}

7️⃣ 用户上下文工具类

BaseContext.java

java 复制代码
public class BaseContext {
    public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    public static Long getCurrentId() {
        return threadLocal.get();
    }
    
    public static void setCurrentId(Long id) {
        threadLocal.set(id);
    }
}

查看购物车

需求分析和设计

代码开发

1️⃣ 控制层 (Controller)

ShoppingCartController.java

java 复制代码
@GetMapping("/list")
@ApiOperation("查看购物车")
public Result<List<ShoppingCart>> list (){
    List<ShoppingCart> list = shoppingCartService.showShoppingCart();
    return Result.success(list);
}
  • 路由GET /user/shoppingCart/list
  • 返回类型Result<List<ShoppingCart>> - 包装了购物车列表
  • 功能:查询当前用户的购物车列表并返回

2️⃣ 服务实现层 (Service Implementation)

ShoppingCartServiceImpl.java

java 复制代码
//查看购物车
public List<ShoppingCart> showShoppingCart(){
    //获取到当前微信用户的id
    Long userId = BaseContext.getCurrentId();
    ShoppingCart shoppingCart = ShoppingCart.builder()
            .userId(userId)
            .build();
    List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
    return list;
}
  1. 用户隔离 :通过 BaseContext.getCurrentId() 获取当前登录用户ID
  2. 构建查询条件 :只按 userId 查询,确保用户只能看到自己的购物车
  3. 调用Mapper:执行数据库查询并返回结果

3️⃣ Mapper 接口层

ShoppingCartMapper.java

java 复制代码
@Mapper
public interface ShoppingCartMapper {
    //动态条件查询
    List<ShoppingCart> list(ShoppingCart shoppingCart);
    
    //根据id修改商品数量
    @Update("update shopping_cart set number = #{number} where id = #{id}")
    void updateNumberById(ShoppingCart shoppingCart);
    
    //插入购物车数据
    @Insert("insert into shopping_cart...")
    void insert(ShoppingCart shoppingCart);
}

4️⃣ MyBatis XML 映射文件 核心SQL

ShoppingCartMapper.xml

XML 复制代码
<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>

🔄 完整请求流程

XML 复制代码
前端 GET /user/shoppingCart/list
              ↓
ShoppingCartController.list()
              ↓
ShoppingCartServiceImpl.showShoppingCart()
    ├── 1. 获取当前用户ID (BaseContext.getCurrentId())
    ├── 2. 构建查询条件: ShoppingCart(userId=当前用户)
    └── 3. 调用 shoppingCartMapper.list()
              ↓
         ShoppingCartMapper.xml.list()
              ↓
         执行动态SQL: SELECT * FROM shopping_cart WHERE user_id = ?
              ↓
         返回 List<ShoppingCart>
              ↓
    Result.success(list) 包装结果
              ↓
前端收到购物车列表

清空购物车

需求分析和设计

代码开发

1️⃣ 控制层 (Controller)

ShoppingCartController.java

java 复制代码
//清空购物车
@DeleteMapping("/clean")
@ApiOperation("清空购物车")
public Result clean(){
    shoppingCartService.cleanShoppingCart();
    return Result.success();
}

2️⃣ 服务接口层 (Service Interface)

ShoppingCartService.java

java 复制代码
//清空购物车
void cleanShoppingCart();

3️⃣ 服务实现层 (Service Implementation) 核心逻辑

ShoppingCartServiceImpl.java

java 复制代码
//清空购物车
public void cleanShoppingCart(){
    //获取到当前微信用户的id
    Long userId = BaseContext.getCurrentId();
    shoppingCartMapper.deleteByUserId(userId);
}
  1. 用户隔离 :通过 BaseContext.getCurrentId() 获取当前登录用户ID
  2. 只做一件事 :调用 shoppingCartMapper.deleteByUserId(userId) 删除该用户的所有购物车数据
  3. 简洁至上:清空购物车不需要复杂的业务逻辑,只需按用户ID删除

4️⃣ 数据访问层 (Mapper) ⭐ 核心SQL

ShoppingCartMapper.java

java 复制代码
//根据用户id删除购物车数据
@Delete("delete from shopping_cart where user_id = #{userId}")
void deleteByUserId(Long userId);

🔄 完整请求流程

java 复制代码
前端 DELETE /user/shoppingCart/clean
              ↓
ShoppingCartController.clean()
              ↓
ShoppingCartServiceImpl.cleanShoppingCart()
    ├── 1. 获取当前用户ID (BaseContext.getCurrentId())
    └── 2. 调用 shoppingCartMapper.deleteByUserId(userId)
              ↓
         执行SQL: DELETE FROM shopping_cart WHERE user_id = ?
              ↓
         数据库中该用户的所有购物车记录被删除
              ↓
    Result.success()  // 返回成功
              ↓
前端收到成功响应,购物车已清空

至此,操作购物车的代码开发已经全部结束

相关推荐
xinjia_ctrl19 分钟前
暑假实习总结
git·后端·spring·maven·intellij-idea
liangsheng_g27 分钟前
SpringAOP拦截器链递归与事务钩子补偿源码实战
java·spring
SL_staff32 分钟前
制造业私有化文档平台的技术实践:从知识孤岛到可追溯知识资产
java·spring·开源
泡泡鱼(敲代码中)2 小时前
MySQL基础学习笔记:从数据模型到DDL全掌握
开发语言·数据库·笔记·学习·mysql
SL_staff2 小时前
3天上线OKR系统:一名HR与1名工程师如何用JVS完成全栈交付
java·低代码·开源
IT_陈寒2 小时前
Java Stream处理大集合,我的内存怎么就炸了
前端·人工智能·后端
悟空码字2 小时前
四轮对话两张配图:用 WorkBuddy 优化公众号发文配图的实战指南
人工智能·后端·腾讯
ServBay2 小时前
xAI的 Grok Bot发布,AI 已经学会自己上班了
后端·ai编程·grok
分支预测失败2 小时前
RISC-V 多核缓存一致性机制解析:MESI 协议族、CMO 扩展与 Linux 同步原语
后端
n8n2 小时前
Spring AI 检索增强生成(RAG)实战:让模型掌握你的私有知识
后端