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

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

相关推荐
lhldsg5 分钟前
全民健身解决方案:从共享球场到智能运营的技术实践
java·大数据·开发语言·需求分析
vipxieliang8 分钟前
ValidX时间注解完全指南:10种时间验证注解详解
java·后端
七牛开发者10 分钟前
解读 Cordis:dsh 一切皆插件背后的运行时设计
前端·javascript·后端
_遥远的救世主_24 分钟前
异步架构与消息治理:幂等性与可恢复性
后端
雨辰AI25 分钟前
openGauss 生产运维避坑指南|适配信创项目改造核心难点
java·运维·后端
_遥远的救世主_30 分钟前
SaaS 工程系统超越多租户的结构性思考
后端
长大198837 分钟前
一键生成 K8s 配置:.NET Aspire 让云原生开发变得如此简单
后端
大勇前进40 分钟前
什么是 MCP(模型上下文协议)?.NET 开发者如何抢占 AI 工具链新风口
后端
名字还没想好☜43 分钟前
Java 21 switch 模式匹配实战:sealed 接口 + record 替代 if-instanceof 链
java·人工智能·后端·python·spring
devilnumber1 小时前
Java 30 组高频技术 / 知识点多角度对比
java·开发语言