📚 目录(点击跳转对应章节)
一、Spring Task定时任务实现
二、WebSocket实现实时通信
三、实际应用场景
总结
在现代Web应用开发中,定时任务和实时通信是两个非常重要的功能。本文将深入探讨苍穹外卖项目中如何使用Spring Task实现定时任务以及如何通过WebSocket实现前后端实时通信。
一、Spring Task定时任务实现
1.1 配置启用定时任务
在Spring Boot中使用定时任务非常简单,只需要在主启动类上添加@EnableScheduling注解即可启用定时任务功能。
@SpringBootApplication@EnableScheduling//开启定时任务功能publicclassSkyApplication{publicstaticvoidmain(String[]args){SpringApplication.run(SkyApplication.class,args);log.info("server started");}}1.2 定时任务实现
在苍穹外卖项目中,所有定时任务都被封装在OrderTask类中,该类使用@Component注解标记为Spring组件。
处理超时未支付订单
/** * 处理支付超时订单 */@Scheduled(cron="0 * * * * ?")//每分钟执行一次publicvoidprocessTimeoutOrder(){log.info("处理支付超时订单:{}",newDate());LocalDateTimetime=LocalDateTime.now().plusMinutes(-15);// select * from orders where status = 1 and order_time < 当前时间-15分钟List<Orders>ordersList=orderMapper.getByStatusAndOrdertimeLT(Orders.PENDING_PAYMENT,time);if(ordersList!=null&&!ordersList.isEmpty()){ordersList.forEach(order->{order.setStatus(Orders.CANCELLED);order.setCancelReason(MessageConstant.PAYMENT_TIMEOUT);order.setCancelTime(LocalDateTime.now());orderMapper.update(order);});}}这个任务每分钟执行一次,查找超过15分钟仍未支付的订单,并将其状态更新为已取消。
处理"派送中"状态的订单
/** * 处理"派送中"状态的订单 */@Scheduled(cron="0 0 1 * * ?")//每日凌晨1点执行一次publicvoidprocessDeliveryOrder(){log.info("处理派送中订单:{}",newDate());// select * from orders where status = 4 and order_time < 当前时间-1小时LocalDateTimetime=LocalDateTime.now().plusHours(-1);List<Orders>ordersList=orderMapper.getByStatusAndOrdertimeLT(Orders.DELIVERY_IN_PROGRESS,time);if(ordersList!=null&&!ordersList.isEmpty()){ordersList.forEach(order->{order.setStatus(Orders.COMPLETED);orderMapper.update(order);});}}这个任务每天凌晨1点执行一次,自动完成超过1小时的"派送中"状态订单。
1.3 数据库查询支持
为了支持定时任务的查询需求,在OrderMapper中定义了相应的查询方法:
/** * 根据状态和下单时间查询订单 * * @param status * @param orderTime * @return */List<Orders>getByStatusAndOrdertimeLT(@Param("status")Integerstatus,@Param("orderTime")LocalDateTimeorderTime);对应的SQL语句在OrderMapper.xml中定义:
<selectid="getByStatusAndOrdertimeLT"resultType="com.sky.entity.Orders">select * from orders where status = #{status} and order_time<#{orderTime}</select>二、WebSocket实现实时通信
2.1 WebSocket配置
WebSocket的配置通过WebSocketConfiguration类实现:
@ConfigurationpublicclassWebSocketConfiguration{@BeanpublicServerEndpointExporterserverEndpointExporter(){returnnewServerEndpointExporter();}}这个配置类启用了WebSocket的端点注册功能。
2.2 WebSocket服务端实现
WebSocket服务端的核心实现位于WebSocketServer类中:
@Component@ServerEndpoint("/ws/{sid}")publicclassWebSocketServer{//存放会话对象privatestaticMap<String,Session>sessionMap=newHashMap<>();/** * 连接建立成功调用的方法 */@OnOpenpublicvoidonOpen(Sessionsession,@PathParam("sid")Stringsid){System.out.println("客户端:"+sid+"建立连接");sessionMap.put(sid,session);}/** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息 */@OnMessagepublicvoidonMessage(Stringmessage,@PathParam("sid")Stringsid){System.out.println("收到来自客户端:"+sid+"的信息:"+message);}/** * 连接关闭调用的方法 * * @param sid */@OnClosepublicvoidonClose(@PathParam("sid")Stringsid){System.out.println("连接断开:"+sid);sessionMap.remove(sid);}/** * 群发 * * @param message */publicvoidsendToAllClient(Stringmessage){Collection<Session>sessions=sessionMap.values();for(Sessionsession:sessions){try{//服务器向客户端发送消息session.getBasicRemote().sendText(message);}catch(Exceptione){e.printStackTrace();}}}}2.3 WebSocket关键特性说明
端点路径:通过@ServerEndpoint
("/ws/{sid}")注解指定WebSocket的访问路径,其中{sid}是客户端标识符。生命周期方法:
- @OnOpen:当客户端建立连接时触发
- @OnMessage:当收到客户端消息时触发
- @OnClose:当连接关闭时触发
会话管理:使用HashMap存储客户端会话,便于后续向特定客户端或所有客户端发送消息。
消息推送:提供了sendToAllClient方法,可向所有连接的客户端广播消息。
三、实际应用场景
3.1 定时任务应用场景
在苍穹外卖项目中,定时任务主要用于:
- 订单状态自动处理:自动取消超时未支付订单,自动完成配送完成的订单
- 数据清理:定期清理过期数据
- 状态同步:定期同步第三方平台的数据状态
3.2 WebSocket应用场景
WebSocket在该项目中主要用于:
- 订单状态通知:当订单状态发生变化时,实时通知管理端页面更新
- 实时消息推送:向客户端推送重要通知或提醒
- 聊天功能:实现客服或用户间实时沟通
总结
苍穹外卖项目展示了Spring Task和WebSocket在实际项目中的典型应用。定时任务帮助我们自动化处理周期性任务,而WebSocket实现了服务器与客户端之间的实时双向通信。这两种技术的结合使应用程序能够提供更流畅的用户体验和更高的自动化水平。
在实际开发中,合理运用这些技术能显著提升系统的可用性和响应速度,为用户提供更好的服务体验。