news 2026/6/18 20:48:04

♪苍穹外卖♪Day9 | 项目日记

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
♪苍穹外卖♪Day9 | 项目日记

今日目标

  • 实现订单定时任务(超时自动取消、自动完成)
  • 集成 WebSocket 实现来单提醒和催单功能
  • 开始数据统计报表模块

一、订单定时任务

1.1 为什么需要定时任务?

有些业务不能等用户主动操作,需要系统自动处理:

  • 超时取消:用户下单后15分钟未支付,自动取消订单
  • 自动完成:订单派送中超过一定时间,自动标记为已完成

这些场景用 Spring 的@Scheduled注解实现。

1.2 订单超时自动取消

每分钟执行一次,查找超过15分钟未支付的订单,自动取消:

@Component@Slf4jpublicclassOrderTask{@AutowiredprivateOrderMapperorderMapper;/** * 处理超时订单,每分钟检查一次 */@Scheduled(cron="0 * * * * ?")publicvoidprocessTimeoutOrder(){log.info("处理超时订单:{}",LocalDateTime.now());// 查询超过15分钟未支付的订单LocalDateTimetime=LocalDateTime.now().plusMinutes(-15);List<Orders>ordersList=orderMapper.getByStatusAndOrderTimeLT(Orders.PENDING_PAYMENT,time);if(ordersList!=null&&ordersList.size()>0){for(Ordersorders:ordersList){orders.setStatus(Orders.CANCELLED);orders.setCancelReason("订单超时,自动取消");orders.setCancelTime(LocalDateTime.now());orderMapper.update(orders);}}}}

1.3 订单自动完成

每天凌晨1点执行,查找派送中超过60分钟的订单,自动完成:

/** * 处理派送中的订单,每天凌晨1点执行 */@Scheduled(cron="0 0 1 * * ?")publicvoidprocessDeliveryOrder(){log.info("处理派送中订单:{}",LocalDateTime.now());LocalDateTimetime=LocalDateTime.now().plusMinutes(-60);List<Orders>ordersList=orderMapper.getByStatusAndOrderTimeLT(Orders.DELIVERY_IN_PROGRESS,time);if(ordersList!=null&&ordersList.size()>0){for(Ordersorders:ordersList){orders.setStatus(Orders.COMPLETED);orders.setDeliveryTime(LocalDateTime.now());orderMapper.update(orders);}}}

1.4 Cron 表达式速查

表达式含义
0 * * * * ?每分钟整点执行
0 0 1 * * ?每天凌晨1点执行
0/5 * * * * ?每5秒执行一次

格式:秒 分 时 日 月 周

1.5 Mapper 新增

@Select("select * from orders where status = #{status} and order_time < #{orderTime}")List<Orders>getByStatusAndOrderTimeLT(Integerstatus,LocalDateTimeorderTime);

二、WebSocket 实时消息推送

2.1 为什么需要 WebSocket?

传统 HTTP 是"请求-响应"模式,服务端不能主动通知客户端。但来单提醒需要服务端主动推送消息给管理端,这时候就需要 WebSocket 长连接。

2.2 配置

注册ServerEndpointExporterBean,让 Spring 支持 WebSocket:

@ConfigurationpublicclassWebSocketConfiguration{@BeanpublicServerEndpointExporterserverEndpointExporter(){returnnewServerEndpointExporter();}}

2.3 服务端实现

@Component@ServerEndpoint("/ws/{sid}")@Slf4jpublicclassWebSocketServer{// 存放连接的客户端privatestaticMap<String,Session>sessionMap=newHashMap<>();@OnOpenpublicvoidonOpen(Sessionsession,@PathParam("sid")sid){log.info("客户端:{} 建立连接",sid);sessionMap.put(sid,session);}@OnClosepublicvoidonClose(@PathParam("sid")sid){log.info("客户端:{} 断开连接",sid);sessionMap.remove(sid);}@OnMessagepublicvoidonMessage(Stringmessage,@PathParam("sid")sid){log.info("收到来自客户端:{} 的信息:{}",sid,message);}/** * 群发消息给所有客户端 */publicvoidsendToAllClient(Stringmessage){try{for(Sessionsession:sessionMap.values()){log.info("推送消息给客户端:{}",message);session.getBasicRemote().sendText(message);}}catch(IOExceptione){log.error("推送消息失败:{}",e.getMessage());}}}

2.4 来单提醒

用户支付成功后,通过 WebSocket 向管理端推送新订单通知:

// PayNotifyController 中@AutowiredprivateWebSocketServerwebSocketServer;@RequestMapping("/paySuccess")publicvoidpaySuccessNotify(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{// ... 解密、更新订单状态 ...// 推送来单提醒webSocketServer.sendToAllClient("来单提醒:订单号 "+outTradeNo);responseToWeixin(response);}

2.5 催单功能

用户对已接单的订单进行催单:

@GetMapping("/reminder/{id}")publicResultreminder(@PathVariable("id")Longid){orderService.reminder(id);returnResult.success();}
publicvoidreminder(Longid){OrdersordersDB=orderMapper.getById(id);if(ordersDB==null){thrownewOrderBusinessException(MessageConstant.ORDER_NOT_FOUND);}// 只有待接单和已确认状态才能催单if(!ordersDB.getStatus().equals(Orders.TO_BE_CONFIRMED)&&!ordersDB.getStatus().equals(Orders.CONFIRMED)){thrownewOrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);}// 通过WebSocket推送催单消息webSocketServer.sendToAllClient("催单提醒:订单号 "+ordersDB.getNumber());}

三、数据统计报表(进行中)

新增ReportController,按日期范围查询营业额:

@RestController("adminReportController")@RequestMapping("/admin/report")publicclassReportController{@AutowiredprivateReportServicereportService;@GetMapping("/turnoverStatistics")publicResult<TurnoverReportVO>turnoverStatistics(LocalDatebegin,LocalDateend){TurnoverReportVOreportVO=reportService.getTurnoverStatistics(begin,end);returnResult.success(reportVO);}}

目前先实现了日期列表生成,营业额数据查询还在完善中。


四、项目整体进度

模块状态
员工管理✅ 完成
分类管理✅ 完成
菜品管理✅ 完成
套餐管理✅ 完成
文件上传✅ 完成
店铺管理✅ 完成
微信登录✅ 完成
购物车✅ 完成
地址簿✅ 完成
订单管理✅ 完成
微信支付✅ 完成
定时任务✅ 完成
WebSocket 来单提醒✅ 完成
催单功能✅ 完成
数据统计报表🔧 进行中

五、今日总结

今天学了三个新技术:

  1. Spring 定时任务@Scheduled+ Cron 表达式,实现订单超时自动取消和自动完成
  2. WebSocket@ServerEndpoint@OnOpen@OnClose@OnMessage,实现服务端主动推送消息
  3. 数据报表:日期范围查询,营业额统计接口(进行中)

WebSocket 是之前没接触过的技术,理解"长连接"和"双向通信"花了点时间。但实际写起来比想象中简单,核心就是维护一个 Session Map,需要推送时遍历所有 Session 发送消息。


苍穹外卖 Day9 完成 ✅

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/18 20:44:52

Gemini Pro定价背后的AI服务真实成本逻辑

1. 这不是涨价&#xff0c;是AI服务进入“真实成本时代”的标志性事件Gemini Pro会员定价每月19.99美元&#xff0c;并附带两个月免费试用期——这个数字本身不惊人&#xff0c;真正值得从业者驻足细看的&#xff0c;是它背后折射出的整个AIGC产业底层逻辑的彻底转向。我从2018…

作者头像 李华
网站建设 2026/6/18 20:43:53

分层记忆缓冲:AI大模型长文本处理的“记忆宫殿”

在认知科学中&#xff0c;人类记忆并非单一容器&#xff0c;而是由感觉记忆、短时记忆和长时记忆构成的分层系统。计算机架构师也早已深谙此道——从L1缓存到内存再到磁盘&#xff0c;逐级扩展容量&#xff0c;每一层都平衡着速度与成本。如今&#xff0c;这个思想正在大语言模…

作者头像 李华
网站建设 2026/6/18 20:42:11

ERPNext完整入门指南:如何免费获得企业级ERP系统

ERPNext完整入门指南&#xff1a;如何免费获得企业级ERP系统 【免费下载链接】erpnext Free and Open Source Enterprise Resource Planning (ERP) 项目地址: https://gitcode.com/GitHub_Trending/er/erpnext 还在为商业ERP系统的高昂费用和复杂部署而烦恼吗&#xff1…

作者头像 李华
网站建设 2026/6/18 20:41:12

艺学师汇学员 AIGC 影视创作成长案例实录

随着AIGC技术深度渗透影视、短视频、数字文创领域&#xff0c;AI影视创作已然从行业专业技能&#xff0c;转变为大众副业增收、职场升级、应届生就业突围的优质核心赛道。但当前市面上绝大多数AI影视教学存在明显短板&#xff0c;普遍重理论灌输、轻实战落地&#xff0c;多数学…

作者头像 李华