苍穹外卖【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()  // 返回成功
              ↓
前端收到成功响应,购物车已清空

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

相关推荐
敲代码的嘎仔1 小时前
从零搭建微服务:Spring Cloud Alibaba 全家桶踩坑实录(Nacos + OpenFeign + Gateway + Sentinel)
java·spring boot·spring·spring cloud·微服务·gateway·sentinel
程序员爱钓鱼1 小时前
Rust 所有权 Ownership 详解:理解内存安全的核心机制
前端·后端·rust
JaguarJack1 小时前
PHP 引用计数机制深度解析
后端·php·服务端
小码农 - 初6 小时前
MySQL 增删改查
mysql
陈随易10 小时前
FFmpeg 9.0 发布,代号 Lei,音视频处理再升级
前端·后端·程序员
凌虚13 小时前
面向 MySQL 用户的 PostgreSQL 快速上手指南
数据库·后端·架构
五阿哥永琪13 小时前
MySQL中操作json的函数!
数据库·mysql·json
来者皆善13 小时前
了解Mysql优化吗?如何优化索引?
数据库·mysql
都叫我大帅哥13 小时前
Java JJWT 完全指南:从入门到生产级实践
java