苍穹外卖【day8| 用户下单】
个人主页:一条泥憨鱼(欢迎各位大佬莅临)精选专栏传送门:❄️《数据结构》 ❄️《AI与Agent那些事》❄️《从0开始学计算机网络》 ❄️《后端开发》需求分析和设计代码开发第1层Controller — 接收请求OrderController.javaRestController(userOrderController) RequestMapping(/user/order) Api(tags 用户端订单相关接口) Slf4j public class OrderController { Autowired private OrderService orderService; PostMapping(/submit) ApiOperation(用户下单) public ResultOrderSubmitVO submit(RequestBody OrdersSubmitDTO ordersSubmitDTO){ log.info(用户下单参数为{}, ordersSubmitDTO); OrderSubmitVO orderSubmitVO orderService.submitOrder(ordersSubmitDTO); return Result.success(orderSubmitVO); } }PostMapping(/submit)— 接口路径为POST /user/order/submitRequestBody OrdersSubmitDTO— 前端 JSON 自动反序列化为 DTO 对象Slf4j— Lombok 自动生成log对象用于记录日志Result.success(...)— 统一响应格式包裹返回数据第2层DTO — 前端提交的数据结构OrdersSubmitDTO.javaData public class OrdersSubmitDTO implements Serializable { private Long addressBookId; // 地址簿id private int payMethod; // 付款方式1微信 2支付宝 private String remark; // 备注 private LocalDateTime estimatedDeliveryTime; // 预计送达时间 private Integer deliveryStatus; // 配送状态1立即送出 0选择具体时间 private Integer tablewareNumber; // 餐具数量 private Integer tablewareStatus; // 餐具数量状态 private Integer packAmount; // 打包费 private BigDecimal amount; // 总金额 }这里前端提交的是用户下单时选择的信息不包含具体菜品菜品从购物车取。第3层Service 核心业务逻辑 — 分步详解OrderServiceImpl.java 的submitOrder方法整个流程分为6 个步骤步骤 ①校验地址簿是否存在AddressBook addressBook addressBookMapper.getById(ordersSubmitDTO.getAddressBookId()); if (addressBook null) { throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL); }根据前端传来的addressBookId查询地址表如果地址不存在抛出业务异常阻止下单同时这个addressBook对象后面还要用来提取收货人姓名、手机号步骤 ②获取当前用户ID 校验购物车Long userId BaseContext.getCurrentId(); ShoppingCart shoppingCart new ShoppingCart(); shoppingCart.setUserId(userId); ListShoppingCart shoppingCartList shoppingCartMapper.list(shoppingCart); if (shoppingCartList null || shoppingCartList.size() 0) { throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL); }BaseContext.getCurrentId()是从ThreadLocal中取出当前登录用户的 ID由 JWT 拦截器在请求进入时存入用userId查询购物车表得到该用户所有购物车商品购物车为空则抛出异常阻止下单这个shoppingCartList后面要用来生成订单明细步骤 ③组装 Orders 对象并插入订单表Orders orders new Orders(); BeanUtils.copyProperties(ordersSubmitDTO, orders); // 拷贝DTO同名属性 orders.setOrderTime(LocalDateTime.now()); // 下单时间 当前时间 orders.setPayStatus(Orders.UN_PAID); // 支付状态 未支付(0) orders.setStatus(Orders.PENDING_PAYMENT); // 订单状态 待付款(1) orders.setNumber(String.valueOf(System.currentTimeMillis())); // 订单号 时间戳 orders.setPhone(addressBook.getPhone()); // 从地址中取手机号 orders.setConsignee(addressBook.getConsignee()); // 从地址中取收货人 orders.setUserId(userId); // 设置用户ID orderMapper.insert(orders); // 插入数据库BeanUtils.copyProperties(ordersSubmitDTO, orders)— Spring 的工具类将 DTO 中同名属性自动拷贝到 Orders 实体如payMethod、amount、remark等setNumber(String.valueOf(System.currentTimeMillis()))— 用时间戳作为订单号简单但有碰撞风险生产环境应用雪花算法orderMapper.insert(orders)对应的 XML 中配置了useGeneratedKeystrue keyPropertyid插入后orders.getId()会自动回填主键值后续步骤要用步骤 ④遍历购物车生成订单明细列表ListOrderDetail orderDetailList new ArrayList(); for (ShoppingCart cart : shoppingCartList) { OrderDetail orderDetail new OrderDetail(); BeanUtils.copyProperties(cart, orderDetail); // 拷贝购物车属性 orderDetail.setOrderId(orders.getId()); // 关联订单ID orderDetailList.add(orderDetail); } orderDetailMapper.insertBatch(orderDetailList); // 批量插入BeanUtils.copyProperties(cart, orderDetail)自动拷贝同名属性orderDetail.setOrderId(orders.getId())是手动设置的因为购物车没有orderId需要关联到刚创建的订单insertBatch使用 MyBatis 的foreach动态拼接多行 VALUES一条 SQL 插入所有明细步骤 ⑤清空购物车shoppingCartMapper.deleteByUserId(userId);下单成功后删除该用户购物车中的所有数据。对应的 SQLDELETE FROM shopping_cart WHERE user_id #{userId}步骤 ⑥封装 VO 返回结果OrderSubmitVO orderSubmitVO OrderSubmitVO.builder() .id(orders.getId()) // 订单ID .orderTime(orders.getOrderTime()) // 下单时间 .orderNumber(orders.getNumber()) // 订单号 .orderAmount(orders.getAmount()) // 订单金额 .build(); return orderSubmitVO;OrderSubmitVO 返回给前端 4 个字段字段说明id订单IDorderNumber订单号时间戳orderAmount订单总金额orderTime下单时间前端拿到这些数据后跳转到支付页面。四、完整数据流图┌─────────────────────────────────────────────────────────────────┐ │ 前端 POST /user/order/submit │ │ Body: { addressBookId, payMethod, amount, remark, ... } │ └──────────────────────────┬──────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ OrderController.submit(OrdersSubmitDTO) │ │ → orderService.submitOrder(ordersSubmitDTO) │ └──────────────────────────┬──────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ OrderServiceImpl.submitOrder() [Transactional 事务保护] │ │ │ │ ① 查地址 → addressBookMapper.getById(...) │ │ ├─ null → 抛异常 AddressBookBusinessException │ │ └─ 有值 → 继续 │ │ │ │ ② 查购物车 → shoppingCartMapper.list(userId) │ │ ├─ 空 → 抛异常 ShoppingCartBusinessException │ │ └─ 有数据 → 继续 │ │ │ │ ③ 组装 Orders → orderMapper.insert(orders) │ │ └─ orders.id 自动回填自增主键 │ │ │ │ ④ 遍历购物车 → 生成 OrderDetail 列表 │ │ └─ orderDetailMapper.insertBatch(list) │ │ │ │ ⑤ 清空购物车 → shoppingCartMapper.deleteByUserId(userId) │ │ │ │ ⑥ 封装 OrderSubmitVO → return │ └──────────────────────────┬──────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ 前端收到 ResultOrderSubmitVO │ │ → 跳转支付页面 │ └─────────────────────────────────────────────────────────────────┘五、关键设计要点总结要点说明Transactional整个方法在一个事务中步骤③④⑤任意一步失败都会回滚保证数据一致性useGeneratedKeystrue插入 orders 后自动回填主键 ID供步骤④使用BeanUtils.copyProperties减少手写 setterDTO→Entity、Cart→OrderDetail 都复用了此工具BaseContext(ThreadLocal)从 JWT 令牌解析出的用户 ID 存入 ThreadLocalService 层直接取用无需层层传参批量插入insertBatch用一条 SQL 插入所有订单明细避免循环单条插入的性能问题Builder 模式OrderSubmitVO.builder()...build()链式构建对象代码清晰可读

相关新闻

从聊天系统到 AI 智能客服: 从文本到图片与情绪、多模态客服与实时智能分流

从聊天系统到 AI 智能客服: 从文本到图片与情绪、多模态客服与实时智能分流

AI 智能客服技术专题第四期 面向后端工程师、AI 工程师和技术负责人售后客服往往从一张图片开始:衣物破损、包裹压坏,或是实物与订单不符。图片能补足文本难以描述的细节,却不能直接作为退款、换货或赔付的依据。它必须先经过文件安全检查、视…

2026/10/26 6:52:50 阅读更多 →
从零吃透 MQTT 通信|第 2 章:裸机环境手动构建 MQTT 协议栈,报文组包与解析实现

从零吃透 MQTT 通信|第 2 章:裸机环境手动构建 MQTT 协议栈,报文组包与解析实现

专栏说明:本章不依赖 paho‑mqtt 等第三方库,完全基于 C 语言实现 MQTT3.1.1 报文封装、报文解析。面向 STM32 裸机、无操作系统 MCU,聚焦协议底层,帮助读者理解每一字节报文的构成,为后续 RTOS 工程、设备对接云平台打…

2026/10/24 1:23:05 阅读更多 →
2024年权威水肥一体化服务商排名,帮你轻松筛选靠谱合作对象

2024年权威水肥一体化服务商排名,帮你轻松筛选靠谱合作对象

注:目前水肥一体化行业186 的 5342 规格 1288 并无官方发布的权威排名,本文整理的是不同定位的主流服务商分类,仅作为大家选型参考,方便大家匹配自身需求筛选合作对象。做过高标准农田项目、规模化种植基地的朋友都懂&#xff0c…

2026/10/25 12:21:57 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/26 12:00:21 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/25 22:36:10 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/26 4:52:12 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/26 12:00:21 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/26 5:00:37 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/26 3:16:46 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 12:00:19 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/25 13:21:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 8:34:37 阅读更多 →