当前位置: 首页 > news >正文

苍穹外卖07——来单提醒和客户催单(涉及SpringTask、WebSocket协议、苍穹外卖跳过微信支付同时保证可以收到订单功能)

Spring Task介绍

应用场景:

  • 信用卡每月还款提醒
  • 银行贷款每月还款提醒
  • 火车票销售系统处理未付款订单
  • 入职纪念日为用户发送通知

cron表达式

cron表达式其实就是一个字符串,通过cron表达式可以定义任务触发的时间。

构成规则:分为6或7个域,由空格分隔,每个域代表一个含义。

每个域的含义分别为:秒、分钟、小时、日、月、周、年(可选)。

秒 分钟 小时 日 月 周 年 

2022年10月12日上午9点整对应的cron表达式为:0 0 9 12 10 ? 2022

cron表达式在线生成器:Cron在线生成器 | 程序员导航网

Spring Task 使用步骤:

  1. 导入 Maven 坐标 spring-context(已存在)
  2. 在启动类添加注解 @EnableScheduling 开启任务调度
  3. 自定义定时任务类,新建一个Task包
    @Component
    @Slf4j
    public class MyTask {@Scheduled(cron = "0/5 * * * * ?") // 每五秒触发public void executeTask(){log.info("定时任务开始执行:{}", new Date());}
    }

订单状态定时处理 

@Component  // 将该类标记为Spring组件,以便自动扫描和管理  
@Slf4j  // 使用Lombok的@Slf4j注解,自动生成日志记录器  
public class OrderTask {  @Autowired  // 自动注入OrderMapper依赖  private OrderMapper orderMapper;  @Scheduled(cron = "0 * * * * ?")  // 每分钟执行一次  public void processTimeoutOrder() {  log.info("定时处理超时订单 {}", LocalDateTime.now());  // 记录当前时间的日志  // 当前时间减去15分钟  LocalDateTime time = LocalDateTime.now().plusMinutes(-15);  // 查询状态为待付款且订单时间早于当前时间减去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);  }  }  }  @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行  public void processDeliveryOrder() {  log.info("定时处理配送中的订单 {}", LocalDateTime.now());  // 记录当前时间的日志  // 当前时间减去60分钟  LocalDateTime time = LocalDateTime.now().plusMinutes(-60);  // 查询状态为配送中且订单时间早于当前时间减去60分钟的订单  List<Orders> ordersList = orderMapper.getByStatusAndOrderTimeLT(Orders.DELIVERY_IN_PROGRESS, time);  // 如果查询到的订单列表不为空  if (ordersList != null && ordersList.size() > 0) {  for (Orders orders : ordersList) {  // 将订单状态设置为已完成  orders.setStatus(Orders.COMPLETED);  // 更新订单信息  orderMapper.update(orders);  }  }  }  
}

WebSocket

WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——一次握手,两者之间就可以建立持久性的连接,并进行双向数据传输。

HTTP协议和WebSocket协议对比:

  • HTTP是短连接
  • WebSocket是长连接
  • HTTP通信是单向的,基于请求响应模式
  • WebSocket支持双向通信
  • HTTP和WebSocket底层都是TCP连接

 选择使用 HTTP 协议还是 WebSocket 协议?

使用 HTTP 协议的情况

  1. 请求-响应结构

    • 如果你的应用主要以传统的请求-响应方式工作(例如,加载网页、提交表单等),那么 HTTP 是更合适的。
  2. 无持续连接

    • HTTP 适合于短暂的连接需求,每个请求和响应都是独立的。
  3. 安全和缓存

    • HTTP 支持缓存机制,可以提高静态资源的加载速度,同时可以通过 HTTPS 实现安全传输。
  4. 简单性

    • 对于相对简单的应用,使用 HTTP 通信更为直观和易于实现。

使用 WebSocket 协议的情况

  1. 实时双向通信

    • 当应用需要实时数据交换,如在线聊天、游戏、股票行情更新等,WebSocket 是更好的选择。
  2. 低延迟和高频率数据传输

    • WebSocket 允许在客户端和服务器之间建立持久连接,适用于需要频繁更新或低延迟的数据传输场景。
  3. 高效数据传输

    • WebSocket 在数据传输上比 HTTP 更为高效,因为它减少了开销,适合大规模应用。
  4. 无需频繁连接和断开

    • 如果应用需要保持长连接,WebSocket 可以避免频繁的连接和断开,节省资源和时间。

总结

  • HTTP:适用于传统请求-响应式的应用,简单和一次性的通信。
  • WebSocket:适用于需要实时、双向且高效沟通的应用。

WebSocket入门案例

导入坐标

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>

 导完坐标之后新建配置类,使WebSocket的第三方bean由ioc容器管理

@Configuration
public class WebSocketConfiguration {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

添加websocket的实体类

/*** WebSocket服务*/
@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {//存放会话对象private static Map<String, Session> sessionMap = new HashMap();/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("sid") String sid) {System.out.println("客户端:" + sid + "建立连接");sessionMap.put(sid, session);}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, @PathParam("sid") String sid) {System.out.println("收到来自客户端:" + sid + "的信息:" + message);}/*** 连接关闭调用的方法** @param sid*/@OnClosepublic 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();  // 捕获并打印异常  }  }  }}

苍穹外卖跳过微信支付同时保证可以收到订单功能

苍穹外卖遇到问题(包括跳过微信支付、nodejs不兼容等)-CSDN博客

来单提醒功能代码开发

需求分析和设计

  • 通过WebSocket实现管理端页面和服务端保持长连接状态
  • 当客户支付后,调用WebSocket的相关API实现服务端向客户端推送消息
  • 客户端浏览器解析服务端推送的消息,判断是来单提醒还是客户催单,进行相应的消息提示和语音播报
  • 约定服务端发送给客户端浏览器的数据格式为JSON,字段包括:type, orderId, content
    • type 为消息类型,1为来单提醒 2为客户催单
    • orderId 为订单id
    • content 为消息内容
/*** 订单支付* @param ordersPaymentDTO* @return*/public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {// 当前登录用户idLong userId = BaseContext.getCurrentId();User user = userMapper.getById(userId);JSONObject jsonObject = new JSONObject();jsonObject.put("code","ORDERPAID");OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);vo.setPackageStr(jsonObject.getString("package"));Integer OrderPaidStatus = Orders.PAID;//支付状态,已支付Integer OrderStatus = Orders.TO_BE_CONFIRMED;  //订单状态,待接单LocalDateTime check_out_time = LocalDateTime.now();//更新支付时间orderMapper.updateStatus(OrderStatus, OrderPaidStatus, check_out_time, this.os.getId());//通过websocket向客户端浏览器推送消息 type orderId contentMap map = new HashMap();map.put("type",1);map.put("orderId",this.os.getId());map.put("content","订单号:"+this.os.getNumber());String json = JSON.toJSONString(map);webSocketServer.sendToAllClient(json);return vo;}

如上面的代码,用户支付成功之后修改数据库中记录的订单的状态为已支付,然后发送websocket响应给管理端admin,然后在controller层发送vo实体类的响应给小程序用户端。

//通过websocket向客户端浏览器推送消息 type orderId content
Map map = new HashMap();
map.put("type",1);
map.put("orderId",this.os.getId());
map.put("content","订单号:"+this.os.getNumber());
String json = JSON.toJSONString(map);
webSocketServer.sendToAllClient(json);
return vo; // 发送给小程序端

管理员的浏览器端接收websocket响应。

深入了解websocket

  • websocket使用前一定要建立通信的信道,这样就可以实现双方的相互通信。
  • WebSocket通信通常是由前端负责打开和关闭的,一旦连接建立,前端和后端可以通过这个通道双向发送和接收消息。

客户催单

// controller层
//客户催单@GetMapping("/reminder/{id}")@ApiOperation("客户端提醒")public Result reminder(@PathVariable("id") Long id){orderService.reminder(id);return Result.success();}// service层
public void reminder(Long id) {// 根据id查询订单Orders ordersDB = orderMapper.getById(id);// 校验订单是否存在if (ordersDB == null) {throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);}Map map = new HashMap();map.put("type", 2); // 类型map.put("orderId", id);map.put("content", "订单号: " + ordersDB.getNumber());// 发送websocket消息webSocketServer.sendToAllClient(JSON.toJSONString(map));}

相关文章:

苍穹外卖07——来单提醒和客户催单(涉及SpringTask、WebSocket协议、苍穹外卖跳过微信支付同时保证可以收到订单功能)

Spring Task介绍 应用场景&#xff1a; 信用卡每月还款提醒银行贷款每月还款提醒火车票销售系统处理未付款订单入职纪念日为用户发送通知 cron表达式 cron表达式其实就是一个字符串&#xff0c;通过cron表达式可以定义任务触发的时间。 构成规则&#xff1a;分为6或7个域&…...

C语言二级考试

你必须知道的 二级考试不是编写程序&#xff0c;或者说不只是编程的考核&#xff0c;它还会考核计算机C语言相关语言还有内涵等基础知识&#xff0c;比较全面综合&#xff08;说人话&#xff0c;要看最新考纲具备一定的基础知识&#xff09; 考试时间 120 分钟 分值 100 分&…...

IDEA Maven构建时报错:无效的目标发行版17

报错分析 报错原因&#xff1a;Maven 构建时&#xff0c;Java 版本配置不匹配 我安装的JDK版本是1.8&#xff0c;但由于种种原因&#xff0c;Maven构建时指定了 Java 17 作为目标发行版&#xff0c;从而导致错误 解决方案 首先&#xff0c;java -version&#xff0c;查看环…...

javafx 将项目打包为 Windows 的可执行文件exe

要将 JavaFX 项目打包为 .exe 文件&#xff0c;你可以使用一些工具将你的应用程序封装为 Windows 可执行文件。以下是两种常用的方法&#xff1a; 方法 1&#xff1a;使用 jpackage&#xff08;适用于 JDK 14 及更高版本&#xff09; jpackage 是 JDK 内置的工具&#xff0c;…...

Python操作Excel的库openpyxl使用入门

openpyxl 是一个用于读写 Excel 2010 xlsx/xlsm/xltx/xltm 文件的 Python 库。以下是一些 openpyxl 的基本使用方法&#xff1a; 安装 openpyxl 首先&#xff0c;确保已经安装了 openpyxl。如果没有安装&#xff0c;可以使用以下命令进行安装&#xff1a; pip install openp…...

数据通过canal 同步es,存在延迟问题,解决方案

当使用 Canal 同步数据到 Elasticsearch&#xff08;ES&#xff09;时&#xff0c;出现延迟问题通常源于多个因素&#xff0c;如 Canal 配置、网络延迟、ES 的负载和性能瓶颈等。以下是一些解决方案&#xff0c;帮助减少和解决延迟问题&#xff1a; 1. 优化 Canal 配置 Canal…...

了解Node.js

Node.js是一个基于V8引擎的JavaScript运行时环境&#xff0c;它允许JavaScript代码在服务器端运行&#xff0c;从而实现后端开发。Node.js的出现&#xff0c;使得前端开发人员可以利用他们已经掌握的JavaScript技能&#xff0c;扩展技能树并成为全栈开发人员。本文将深入浅出地…...

Android Studio创建新项目并引入第三方jar、aar库驱动NFC读写器读写IC卡

本示例使用设备&#xff1a;https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1bbW3AUC&ftt&id615391857885 一、打开Android Studio,点击 File> New>New project 菜单&#xff0c;选择 要创建的项目模版&#xff0c;点击 Next 二、输入项目名称…...

Oracle Dataguard(主库为双节点集群)配置详解(4):配置备库

Oracle Dataguard&#xff08;主库为双节点集群&#xff09;配置详解&#xff08;4&#xff09;&#xff1a;配置备库 目录 Oracle Dataguard&#xff08;主库为双节点集群&#xff09;配置详解&#xff08;4&#xff09;&#xff1a;配置备库一、为备库配置静态监听1、配置 li…...

前端炫酷动画--文字(二)

目录 一、弧形边框选项卡 二、零宽字符 三、目录滚动时自动高亮 四、高亮关键字 五、文字描边 六、按钮边框的旋转动画 七、视频文字特效 八、立体文字特效让文字立起来 九、文字连续光影特效 十、重复渐变的边框 十一、磨砂玻璃效果 十二、FLIP动画 一、弧形边框…...

ceph 数据均衡

实现数据均衡的主要方法 在 Ceph 集群中,实现 OSD(对象存储守护进程)之间的数据均衡对于提升性能和资源利用率至关重要。以下是实现数据均衡的主要方法: 1. 调整 OSD 权重(Reweight) 通过调整 OSD 的权重,可以控制数据在各个 OSD 之间的分布。Ceph 提供了根据利用率或…...

代码随想录算法训练营day29

代码随想录算法训练营 —day29 文章目录 代码随想录算法训练营前言一、134. 加油站暴力解法贪心算法 二、135. 分发糖果三、860. 柠檬水找零四、406.根据身高重建队列vector版list版 总结 前言 今天是算法营的第29天&#xff0c;希望自己能够坚持下来&#xff01; 今日任务&a…...

android studio根据包名获取当前安装包信息

package com.example.myapplication2;import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.util.Log;/**** 获取版本信息*/ public class SystemHelper {/*** 获取本地软件版本号*/public stat…...

学习第六十五行

仔细观察键盘&#xff0c;会发现一个$符号&#xff0c;其实是有含义的。 在 shell 脚本中&#xff0c;美元符号 $ 有几种重要的含义&#xff1a; 变量引用&#xff1a;$ 用于引用变量的值。例如&#xff0c;如果你有一个变量 name&#xff0c;可以通过 $name 来获取它的值。 n…...

零碎的知识点(七):线性二次调节器(LQR)是什么?

线性二次调节器&#xff08;LQR&#xff09;是什么&#xff1f; 1. LQR的定义与目标2. LQR的原理性能指标 J J J最优解的计算控制律 3. LQR的性质4. 举例说明问题描述解步骤仿真结果 5. 实际应用总结 线性二次调节器&#xff08;LQR&#xff09; 是一种经典的最优控制方法&…...

Matlab一些使用技巧

代码分段 两个百分号就可以实现代码的分段&#xff0c;不同段之间会以不同的背景色显示&#xff0c;方便调试 如下&#xff1a; %% 腐蚀 stlen TimeWidth*Fs/50; %线性算子的长度&#xff0c;1/100的脉宽&#xff0c;对应0.5us&#xff0c;15个采样点 stlen 100; SE strel…...

Linux 发行版介绍与对比:Red Hat、Ubuntu、Kylin、Debian

Linux 操作系统有众多发行版&#xff08;Distros&#xff09;&#xff0c;每个发行版的设计目标、目标用户、应用场景和使用方式有所不同。常见的 Linux 发行版包括 Red Hat、Ubuntu、Kylin 和 Debian。以下是这些发行版的详细介绍与对比&#xff0c;以及它们的应用场景和使用方…...

从CentOS到龙蜥:企业级Linux迁移实践记录(龙蜥开局)

引言&#xff1a; 在我们之前的文章中&#xff0c;我们详细探讨了从CentOS迁移到龙蜥操作系统的基本过程和考虑因素。今天&#xff0c;我们将继续这个系列&#xff0c;重点关注龙蜥系统的实际应用——特别是常用软件的安装和配置。 龙蜥操作系统&#xff08;OpenAnolis&#…...

java1-相对路径与绝对路径

注意注意~开始新部分啦! 开始正式分享java前,先为大家分享一下一个常用的概念---文件的相对路径与绝对路径. 开篇明义: 相对路径是指一个文件或目录相对于当前工作目录的路径。相对路径不包含根目录&#xff0c;而是从当前目录开始计算。 绝对路径是指一个文件或目录从根目录…...

iChainfo 品牌升級為 ichaingo,打造 Web3 數據基礎設施新標杆

Web3 數據基礎設施服務商 iChainfo 今⽇正式宣佈&#xff0c;全新名稱 「ichaingo」 重磅登場&#xff0c;新的官⽅網站 ichaingo.com 正式上線。此次品牌升級基於 Web3 ⾏業的發展趨勢和公司⾃⾝的戰略布局&#xff0c;旨在為全 球⽤戶提供更準確、即時、全⾯、深⼊的 Web3 數…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中&#xff0c;JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作&#xff08;如 Promise、async/await 等&#xff09;&#xff0c;开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝&#xff08;r…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...