【项目实战 Day10】springboot + vue 苍穹外卖系统(SpringTask + 订单定时处理 + WebSocket + 催单 + 来单提示 完结)
目录
一、Spring Task
1、简介
Spring Task 是 Spring 框架提供的一个定时任务调度器。
它允许开发者以注解或配置的方式,在指定的时间或周期性地执行某个方法。
2、cron表达式
- cron表达式其实就是一个字符串,通过cron表达式可以定义任务触发的时间
- 构成规则:分为6或7个域,由空格分隔开,每个域代表一个含义
- 每个域的含义分别为:秒、分钟、小时、日、月、周、年(可选)
2022年10月12日上午9点的corn表达式为
其中【日】和【周】一般不能同时规定,因为10.12不一定是周几,同理,周五不一定是固定的某日
因此若规定日,则【周】为【?】;若规定周,则【日】为【?】
我们想要生成更为复杂的corn时间表达式,可以问AI
3、入门案例
(1)导入maven(已存在)
(2)启动类添加注解 @EnableScheduling开启任务调度
(3)自定义定时任务类
二、订单状态定时处理模块
1、需求分析
用户下单后可能存在的情况:
- 下单后未支付,订单一直处于【待支付】状态
- 用户收货后管理端未点击完成按钮,订单一直处于【派送中】状态
对于上面两种情况需要通过定时任务来修改订单状态,具体逻辑为:
- 通过定时任务每分钟检查一次是否存在支付超时订单(下单后超过15分钟仍未支付则判定为支付超时订单),如果存在则修改订单状态为【已取消】
- 通过定时任务每天凌晨1点检查一次是否存在【派送中】的订单,如果存在则修改订单状态为【已完成】(在店打烊后统一处理)
2、代码开发
(1)OrderTask
/** * 自定义定时任务类 */ @Component @Slf4j public class OrderTask { @Autowired private OrderMapper orderMapper; /** * 处理超时订单 */ @Scheduled(cron = "0 * * * * ?") //每分钟处理一次 public void processTimeoutOrder(){ log.info("定时处理超时订单:{}", LocalDateTime.now()); //1.找出当前订单超时且状态为【待支付】的订单列表 LocalDateTime time = LocalDateTime.now().plusMinutes(-15);//当前时间-15min List<Orders> ordersList = orderMapper.getByStatusAndOrderTimeLT(Orders.PENDING_PAYMENT, time); //2.将状态更改为【已取消】,并更新取消原因和取消时间 if(!CollectionUtils.isEmpty(ordersList)){ for (Orders od : ordersList) { od.setStatus(Orders.CANCELLED); od.setCancelReason("订单超时,自动取消"); od.setCancelTime(LocalDateTime.now()); orderMapper.update(od); } } } /** * 处理一直派送中的订单 */ @Scheduled(cron = "0 0 1 * * ?")//每天凌晨一点 public void processDeliverOrder(){ log.info("定时处理一直派送中订单:{}", LocalDateTime.now()); //1.找出前一天且状态为【派送中】的订单列表 LocalDateTime time = LocalDateTime.now().plusMinutes(-60);//当前时间-60min List<Orders> ordersList = orderMapper.getByStatusAndOrderTimeLT(Orders.DELIVERY_IN_PROGRESS, time); //2.将状态更改为【已完成】 if(!CollectionUtils.isEmpty(ordersList)){ for (Orders od : ordersList) { od.setStatus(Orders.COMPLETED); orderMapper.update(od); } } } }(2)OrderMapper
/** * 根据订单状态和下单时间查询订单 */ @Select("select * from sky_take_out.orders where status = #{status} and order_time < #{orderTime}") List<Orders> getByStatusAndOrderTimeLT(Integer status,LocalDateTime orderTime);
三、WebSocket
1、简介
WebSocket 是基于 TCP 的一种新的网络协议。
它实现了浏览器与服务器全双工通信:浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。即一次连接,实时更新,用于一些需要即时更新的场景
(1)HTTP协议和WebSocket协议对比
- HTTP是短连接
- WebSocket是长连接
- HTTP通信是单向的,基于请求响应模式
- WebSocket支持双向通信
- HTTP和WebSocket底层都是TCP连接
(2)应用场景
- 视频弹幕
- 网页聊天
- 体育实况更新
- 股票基金报价实时更新
2、入门案例
(1)导入maven
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <scope>compile</scope> </dependency>(2)导入配置类
(3)导入代码
将day10中的代码导入
(4)测试
重新启动项目,在项目登录页面点击登录,若在ide控制台可以看到下面的提示,则表明连接成功
四、来单提醒模块
1、需求分析
- 通过 WebSocket 实现【后端】和【管理系统】保持长连接状态
- 当客户支付后,调用 WebSocket 的相关API实现后端(服务端)向管理系统(客户端)推送消息
- 管理系统浏览器解析后端推送的消息,判断是【来单提醒】还是【客户催单】,进行相应的【消息提示】和【语音播报】
- 约定后端发送给管理系统浏览器的数据格式为JSON,字段包括:type,orderld,content
- type 为消息类型,1为来单提醒 2为客户催单
- orderld 为订单id
- content 为消息内容
2、代码开发
因为我们在day8的支付模块是跳过微信支付的,因此来单提醒模块也同样需要更改
OrderServiceImpl 中的 payment 方法下增加以下代码
//通过WebSocket向客户端浏览器推送消息 type orderId content Map map = new HashMap<>(); map.put("type",1); //1表示来单提醒,2表示客户催单 map.put("orderId",this.orders.getId()); map.put("content","订单号:"+this.orders.getNumber()); String json = JSON.toJSONString(map); //向所有连接的 WebSocket 客户端广播发送 JSON 数据 webSocketServer.sendToAllClient(json);
3、功能测试
启动项目,然后返回登录界面点击【登录】,就能在ide控制台中看到成功连接提示
接着启动小程序,选择若干商品并点击支付,支付成功后,后台管理网页会在右上角弹出窗口,并进行语音播报,若成功显示即为测试成功
五、用户催单模块
1、需求分析
- 通过 WebSocket 实现【后端】页面和【小程序】保持长连接状态
- 当用户催单后,调用 WebSocket 的相关API实现后端(服务端)向小程序(客户端)推送消息
- 小程序解析后端推送的消息,判断是【来单提醒】还是【客户催单】,进行相应的【消息提示】和【语音播报】
- 约定后端发送给小程序的数据格式为JSON,字段包括:type,orderld,content
- type 为消息类型,1为来单提醒 2为客户催单
- orderld 为订单id
- content 为消息内容
2、代码开发
【1】controller层
/** * 用户催单 * @param id * @return */ @GetMapping("/reminder/{id}") @ApiOperation("用户催单") public Result reminder(@PathVariable Long id){ orderService.reminder(id); return Result.success(); }【2】service层
/** * 用户催单 * @param id */ public void reminder(Long id) { //根据id查询订单是否存在 Orders orderDB = orderMapper.getById(id); if(orderDB == null){ throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR); } //通过WebSocket向客户端浏览器推送消息 type orderId content Map map = new HashMap<>(); map.put("type",2); //1表示来单提醒,2表示客户催单 map.put("orderId",orderDB.getId()); map.put("content","订单号:"+orderDB.getNumber()); String json = JSON.toJSONString(map); //向所有连接的 WebSocket 客户端广播发送 JSON 数据 webSocketServer.sendToAllClient(json); }
3、功能测试
重新启动项目,在小程序用户订单中点击【催单】,即可在管理系统页面看到催单提示
六、思考:用户催单和来单提示是怎么实现的?
1、来单提示流程
2、用户催单流程
更多推荐

















所有评论(0)