Day10 学习目标与产出
Day10 主要做 3 件事:Spring Task 定时任务、订单状态定时处理、WebSocket + 来单提醒 + 客户催单。
学完你应该能交付:
- 定时任务能跑起来(每分钟/每天定时执行)
- 支付超时订单自动取消、派送中订单自动完成
- 管理端建立 WebSocket 长连接,支付成功“来单提醒”,用户点击“催单”后台弹窗+语音提醒
推荐学习路线
① 先把 Spring Task 跑通
核心点就 3 个:
- 启动类加
@EnableScheduling开启任务调度 - 定义组件类 +
@Scheduled(cron="...") - 观察日志是否按频率输出(比如 5 秒一次)
② 落地:订单状态定时处理(关键业务)
需求是两类异常订单要“自动收口”:
- 待支付:下单超过 15 分钟仍未支付 → 自动取消(每分钟检查一次)
- 派送中:一直不点完成 → 凌晨 1 点检查并自动完成
落地结构:
(1) 定时任务类 OrderTask
processTimeoutOrder():cron 每分钟一次0 * * * * ?processDeliveryOrder():cron 每天凌晨 1 点0 0 1 * * ?
(2) Mapper 扩展:按状态 + 下单时间查询
getByStatusAndOrdertimeLT(status, orderTime)
(3) 核心处理逻辑
- 超时:
now - 15min查询待支付订单,循环更新为取消 + 原因 + 取消时间 - 派送中:讲义示例用
now - 60min去查询派送中并更新完成(实际业务你也可以按需求调整)
测试建议
- 测试时可以临时把 cron 改成更频繁,方便验证。
- 观察:控制台 SQL + 数据库 orders 表 status 变化。
③ WebSocket 入门:先能“服务端主动推送”
已经把 WebSocket 和 HTTP 的差异、适用场景讲清楚了:WebSocket 长连接、双向通信,但有维护成本与重连问题。
入门案例的最小闭环:
- 浏览器打开
websocket.html,连接ws://localhost:8080/ws/{clientId} - 服务端
@ServerEndpoint("/ws/{sid}")建立连接,保存 session;提供sendToAllClient群发方法 - 配置类注册
ServerEndpointExporter - 定时任务每 5 秒推送一次(用于验证链路)
业务落地:来单提醒 & 客户催单
1) 来单提醒(支付成功后通知商家)
设计思路:管理端与服务端保持 WebSocket 长连接,支付成功后服务端主动推送消息。
约定推送 JSON 格式:type、orderId、content;type=1 来单提醒,type=2 催单。
实现点:在 OrderServiceImpl.paySuccess() 里更新订单后,组装 map 并推送:
type = 1orderId = orders.getId()content = 订单号...webSocketServer.sendToAllClient(JSON.toJSONString(map))
测试路径:登录管理端建立长连接 → 小程序端下单支付 → 管理端弹窗+语音。
2) 客户催单(小程序点“催单”后通知商家)
同样走 WebSocket 推送,只是 type=2。
接口与代码骨架(讲义给了):
- Controller:
GET /reminder/{id}调 service - Service:声明
void reminder(Long id); - ServiceImpl:查订单是否存在,不存在抛异常;存在则推送 type=2 的消息
- Mapper:补
getById
Day10 常见坑
-
cron 写对但不执行:常见原因是启动类漏了
@EnableScheduling。 -
定时任务测试太慢:测试阶段先把 cron 改成更频繁,验证后再改回生产频率。
-
WebSocket 连接不上:
- 服务端要有
@ServerEndpoint("/ws/{sid}"),并注册ServerEndpointExporter。 - 客户端 URL 要匹配:
ws://localhost:8080/ws/{clientId}。
- 服务端要有
-
推送了但前端没弹窗/没语音:先在浏览器控制台确认收到了 JSON(type/orderId/content),再看前端的消息解析分支是否按 type 处理。
-
长连接稳定性:WebSocket 天生要考虑断线/重连(讲义也点到了)。