苍穹外卖day04
Spring Task实现定时处理订单状态
作用:不需要输入提示信号,便可定时自动执行程序
使用步骤
1、启动类上加上注解(@EnableScheduling)开启定时任务调度
2、专门创建一个包来管理执行定时任务的类,该类需要交给IOC容器管理
3、通过注解@Scheduled() + Cron表达式来指定执行时间(通过6|7个域 (秒 分 时 [日] 月 [周] 年),周和日只存在其一)
场景
订单下单后一直没有支付;派送完成后用户没有点击已收货;
示例
@Scheduled(cron = "0 * * * * ? ") //每分钟触发一次 public void processTimeoutOrder(){ log.info("定时处理超时订单:{}", LocalDateTime.now()); LocalDateTime time = LocalDateTime.now().plusMinutes(-15); List<Orders> ordersList = orderMapper.getByStatusAndOrderTimeLT(Orders.PENDING_PAYMENT, time); if(ordersList != null && ordersList.size() > 0){ for (Orders orders : ordersList) { orders.setStatus(Orders.CANCELLED); orders.setCancelReason("订单超时,自动取消"); orders.setCancelTime(LocalDateTime.now()); orderMapper.update(orders); } } }
WebSocket 实现来单提醒
作用:基于TCP的网络协议,仅需一次握手,便可实现浏览器和服务器双向通信
场景:实时通信类、有交换类的游戏或功能
使用流程:
1、导入maven
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
2、创建配置类来配置 WebSocket
/** * WebSocket配置类,用于注册WebSocket的Bean */ @Configuration public class WebSocketConfiguration { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
3、封装一个Socket服务来处理客户端发送的消息
@Component @ServerEndpoint("/ws/{sid}") public class WebSocketServer { //存放会话对象 private static Map<String, Session> sessionMap = new HashMap(); /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session, @PathParam("sid") String sid) { System.out.println("客户端:" + sid + "建立连接"); sessionMap.put(sid, session); } /** * 收到客户端消息后调用的方法 * @param message 客户端发送过来的消息 */ @OnMessage public void onMessage(String message, @PathParam("sid") String sid) { System.out.println("收到来自客户端:" + sid + "的信息:" + message); } /** * 连接关闭调用的方法 * @param sid */ @OnClose public void onClose(@PathParam("sid") String sid) { System.out.println("连接断开:" + sid); sessionMap.remove(sid); } /** * 群发 * @param message */ public void sendToAllClient(String message) { Collection<Session> sessions = sessionMap.values(); for (Session session : sessions) { try { //服务器向客户端发送消息 session.getBasicRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } } }
4、使用
@Component public class WebSocketTask { @Autowired private WebSocketServer webSocketServer; /** * 通过WebSocket每隔5秒向客户端发送消息 */ @Scheduled(cron = "0/5 * * * * ?") public void sendMessageToClient() { webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now())); } }
营业额统计
ServiceImpl
public TurnoverReportVO getTurnoverStatistics(LocalDate begin, LocalDate end) { //当前集合用于存放从begin到end范围内的每天的日期 List<LocalDate> dateList = new ArrayList<>(); dateList.add(begin); while (!begin.equals(end)) { //日期计算,计算指定日期的后一天对应的日期 begin = begin.plusDays(1); dateList.add(begin); } //存放每天的营业额 List<Double> turnoverList = new ArrayList<>(); for (LocalDate date : dateList) { //查询date日期对应的营业额数据,营业额是指:状态为“已完成”的订单金额合计 LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN); LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX); // select sum(amount) from orders where order_time > beginTime and order_time < endTime and status = 5 Map map = new HashMap(); map.put("begin", beginTime); map.put("end", endTime); map.put("status", Orders.COMPLETED); Double turnover = orderMapper.sumByMap(map); turnover = turnover == null ? 0.0 : turnover; turnoverList.add(turnover); } //封装返回结果 return TurnoverReportVO .builder() .dateList(StringUtils.join(dateList, ",")) .turnoverList(StringUtils.join(turnoverList, ",")) .build(); }
Mapper.xml
<select id="sumByMap" resultType="java.lang.Double"> select sum(amount) from orders <where> <if test="begin != null"> and order_time > #{begin} </if> <if test="end != null"> and order_time < #{end} </if> <if test="status != null"> and status = #{status} </if> </where> </select>
订单统计和用户统计功能实现也一样基本为增删改查,不过返回数据的类型之前不同