《苍穹外卖》知识梳理P9-定时任务、来单提醒与用户催单

2024-02-18 18:44

本文主要是介绍《苍穹外卖》知识梳理P9-定时任务、来单提醒与用户催单,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一.定时任务

实现定时任务可以使用spring家族中的sprinig-task;

1.1 spring-task

spring-task是Spring框架的任务调度工具,可以按照约定的时间自动执行某个代码逻辑;

应用场景

  • 信用卡每月归还贷款提醒,定时任务检查,每天查看有没有提醒的人,有的话自动提醒;
  • 车票处理未支付订单(xx分钟之内付款,超时自动取消);
  • 入职纪念日为用户发送通知;

cron表达式的使用

  • 本质上是一个字符串,可以用来定义任务触发的时间;
  • 构成规则:分为6/7个域,由空格隔开,每个域代表一个含义,每个域可以分为:秒,分钟,小时,日,月,周,年(可选),
  • 日和周通常只写一个,另一个写?例如:2023年10月12日上午9点整对应的cron表达式为:0 0 9 12 10 ? 2023
  • cron表达式在线生成器:https://cron.qqe2.com/

入门案例

  • 导入坐标:实际上是spring-context依赖,但是由于spring-boot-starter已经包含了spring-context依赖,因此直接导入springboot的依赖即可,会将context传递过来;
		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency>
  • 在启动类上加入@EnableScheduling注解开启任务调度
  • 自定义定时任务类(写业务逻辑)
	@Component@Slf4j/*** 自定义定时任务类*/public class MyTask {//从第0秒开始,每隔5秒触发一次;@Scheduled(cron = "0/5 * * * * ?")public void executeTask(){log.info("定时任务开始执行......"+ LocalDateTime.now());}}

用户下单之后可能存在

  • 下单之后未支付,订单一直处于“待支付”状态;超时后订单需要自动取消;
  • 用户收获之后未点击“完成”按钮,订单一直处于“派送中”状态;超时后定时任务应该自动完成;

1.2 超时订单的处理

  • 通过定时任务设置每分钟检查一次是否存在支付超时订单(下单完成后超过15分钟仍未支付则判定为超时订单),如果存在则修改订单为“已取消”;
	/*** 处理超时订单,每分钟触发一次*/
//    @Scheduled(cron = "0 * * * * ?")@Scheduled(cron = "0 0/10 * * * ?")  //每10分钟触发一次public void processTimeoutOrder() {log.info("定时处理超市订单...{}", LocalDateTime.now());//查询订单表,时候有处于待付款的订单;LocalDateTime time = LocalDateTime.now().plusMinutes(-15);List<Orders> ordersList = orderMapper.getByStatusAndOrderTime(Orders.PENDING_PAYMENT, time);if (ordersList != null && ordersList.size() != 0) {for (Orders order : ordersList) {order.setStatus(Orders.CANCELLED);order.setCancelReason("订单超时,自动取消");order.setCancelTime(LocalDateTime.now());orderMapper.update(order);}}}

1.3 用户已收到货物但未点击“完成”的仍处于派送中的订单处理

  • 对于派送中的订单,一天只需要检查一次即可(可以设置为每天凌晨4点检查一次),是否存在“派送中”的订单,如果存在,则修改为“已完成”;否则如果一分钟检查一次,可能出现用户还未收到货,但是已经完成了。
	/*** 处理派送中订单,每天触发一次*/@Scheduled(cron = " 0 0 4 * * ? ") //每月每天凌晨四点public void processDeliveryOrder() {log.info("定时处理派送中订单...{}", LocalDateTime.now());//每天凌晨四点清算上一天的派送中订单(小于上一天24:00的订单都完成)LocalDateTime time = LocalDateTime.now().plusMinutes(-240);List<Orders> ordersList = orderMapper.getByStatusAndOrderTime(Orders.DELIVERY_IN_PROGRESS, time);if (ordersList != null && ordersList.size() != 0) {for (Orders order : ordersList) {order.setStatus(Orders.COMPLETED);orderMapper.update(order);}}}

二.WebSocket

  • 基于TCP新的网络协议;实现了浏览器与服务器的全双工通信;浏览器可以同浏览器进行双向数据传输,浏览器与服务器只需要完车一次握手,二者之间就会创建持久性连接,并进行双向数据传输;类似打电话。
  • HTTP协议是一定是客户端先请求服务器,HTTP是短连接单向通信,请求-响应模式,
  • WebSocket与HTTP底层都是基于TCP协议;

应用场景

适用于页面并没有刷新,但是数据在实时更新的场景,即用户;

  • 视频弹幕;
  • 网页聊天;
  • 体育实况更新;
  • 股票基金实时报价;

websocket使用流程

  • 导入maven坐标
		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>
  • 导入websocket配置类
	/*** WebSocket配置类,用于注册WebSocket的Bean*/@Configurationpublic class WebSocketConfiguration {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}
  • 导入websocket服务端代码
	/*** WebSocket服务*/@Component@ServerEndpoint("/ws/{sid}") //websocket客户端请求路径;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();}}}}

可能出现的问题

  • 1.导入代码之后,如果出现了websocket客户端连接失败的问题,可能原因是代码导入之后未重新编译,手动点击“重新构建代码”即可
    在这里插入图片描述
  • 2.由于前边在配置nginx反向代理时,可能会由于IIS占用80端口,导致Nginx无法监听在80端口,因此有2种解决方案:1.关闭IIS服务,2.将监听端口修改为其他端口比如8888端口;由于第一种方案可能带来一些影响并且比较麻烦,因此通常使用第2种方案,但是如果使用第2种方案,现在就会引入这一新的问题:由于NGINX反向代理的存在,请求会被先转发到nginx服务器,再由nginx服务器转发到我的服务器,然而最开始由客户端发送的请求ws://localhost/ws/k3ql4hupss默认是80端口,而我的nginx服务器运行在8888端口,所以就连nginx服务器都无法收到这个请求,更别说我的服务器了,因此会造成服务器无法接收到建立websocket连接的请求;
    在这里插入图片描述
  • 此时如果最开始配置nginx时你使用了第一种方案,那么恭喜你,你不用修改任何东西,即可继续正常运行;如果你使用了第二种方案(我把nginx监听端口设置为了8888端口),此时要么改回80端口,但是需要关闭IIS服务,要么修改前端代码,我直接修改前端代码:找到nginx目录下的html目录,里边部署了sky-take-out的前端工程;
    在这里插入图片描述
  • 进入sky目录下:
    在这里插入图片描述
  • 进入js目录:
    在这里插入图片描述
  • 使用vscode或其他编辑器打开app.d0aa4eb3.js文件,ctrl+F查找"ws://localhost",如图所示,原本为"ws://localhost/ws/“改为"ws://localhost:你的nginx监听端口/ws/”
    在这里插入图片描述
  • 修改之后重启nginx;并记得清除浏览器缓存(我因为没请缓存所以改过之后还是旧的请求想了半天不知道哪出问题…)修改成功之后的效果:
    在这里插入图片描述

三.来单提醒与用户催单

3.1 来单提醒

  • 商家管理端页面与服务端建立长连接;
  • 当支付成功之后,调用websocket的相关API实现服务端向客户端推送消息;
  • 客户端浏览器解析服务端推送的消息,判断是来单提醒还是客户催单,进行相应的消息提示和语音播报;
  • 约定服务端发送给客户端浏览器数据的数据格式为JSON,字段包括:type,orderId,content;
    • type 消息类型1来单提醒,2客户催单;
    • orderId 订单ID;
    • content消息内容;

内网穿透工具cpolar

  • 访问网址cpoloar.com
  • 注册账号并登陆
  • 下载windows版
  • 进行傻瓜式安装
  • 回到cpolar页面,点击“验证”
    在这里插入图片描述

 会得到你的令牌,复制之
 进入到带有cpolar.exe的目录,打开命令行
在这里插入图片描述
 windows下使用命令:

cpolar.exe authtoken 你的authtoken 

 会生成一个内网穿透的配置文件,文件的地址会给出:
在这里插入图片描述
 然后可以临时启动一个服务指定一个IP地址:

cpolar.exe http 8080 

在这里插入图片描述
  此时生成了一个域名并被映射到localhost:8080,使用临时域名访问swagger接口文档(注意复制时如果cmd窗口无法复制,可以右键点击“标记”,在此之后便可以复制)
在这里插入图片描述

修改配置文件

  由于前边使用的模拟微信支付,直接调用了支付成功的接口,所以并没有微信支付的相关配置;

wechat:appid: 你的appidsecret: 你的appsecretnotify-url: https://21e88914.r24.cpolar.top/notify/paySuccessrefund-notify-url: https://21e88914.r24.cpolar.top/notify/refundSuccess

  修改支付成功业务层代码OrderServiceImpl.paySuccess,这里代码中所指出的客户端是商家管理端(由于商家可能打开了多个管理端页面,所以向所有与websocket-server建立了连接的管理端都推送了订单通知)

	/*** 支付成功,修改订单状态** @param outTradeNo*/public void paySuccess(String outTradeNo) {// 当前登录用户idLong userId = BaseContext.getCurrentId();// 根据订单号查询当前用户的订单Orders ordersDB = orderMapper.getByNumberAndUserId(outTradeNo, userId);// 根据订单id更新订单的状态、支付方式、支付状态、结账时间Orders orders = Orders.builder().id(ordersDB.getId()).status(Orders.TO_BE_CONFIRMED).payStatus(Orders.PAID).checkoutTime(LocalDateTime.now()).build();orderMapper.update(orders);//通过websocket向客户端浏览器推送消息(新增消息推送代码)Map map=new HashMap<>();map.put("type",1);map.put("orderId",ordersDB.getId());map.put("content","订单号"+outTradeNo);String json= JSON.toJSONString(map);//推送到所有用户;webSocketServer.sendToAllClient(json);}

3.2 客户催单

  • 商家管理端页面与服务端建立长连接;
  • 当用户催单之后,调用websocket的相关API实现服务端向客户端推送消息;
  • 客户端浏览器解析服务端推送的消息,判断是来单提醒还是客户催单,进行相应的消息提示和语音播报;
  • 约定服务端发送给客户端浏览器数据的数据格式为JSON,字段包括:type,orderId,content;
    • type 消息类型1来单提醒,2客户催单;
    • orderId 订单ID;
    • content消息内容;
      催单业务代码与来单提醒类似:
	/*** 用户催单* @param id*/@Overridepublic void reminder(Long id) {Orders orders=orderMapper.getById(id);if (orders==null){throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);}Map map=new HashMap<>();map.put("type",2);map.put("orderId",id);map.put("content","订单号"+orders.getNumber());String json= JSON.toJSONString(map);log.info("推送消息为:{}",json);//推送到所有的管理端webSocketServer.sendToAllClient(json);}

这篇关于《苍穹外卖》知识梳理P9-定时任务、来单提醒与用户催单的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/722113

相关文章

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

sqlite3 相关知识

WAL 模式 VS 回滚模式 特性WAL 模式回滚模式(Rollback Journal)定义使用写前日志来记录变更。使用回滚日志来记录事务的所有修改。特点更高的并发性和性能;支持多读者和单写者。支持安全的事务回滚,但并发性较低。性能写入性能更好,尤其是读多写少的场景。写操作会造成较大的性能开销,尤其是在事务开始时。写入流程数据首先写入 WAL 文件,然后才从 WAL 刷新到主数据库。数据在开始

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

【Kubernetes】K8s 的安全框架和用户认证

K8s 的安全框架和用户认证 1.Kubernetes 的安全框架1.1 认证:Authentication1.2 鉴权:Authorization1.3 准入控制:Admission Control 2.Kubernetes 的用户认证2.1 Kubernetes 的用户认证方式2.2 配置 Kubernetes 集群使用密码认证 Kubernetes 作为一个分布式的虚拟

ActiveMQ—消息特性(延迟和定时消息投递)

ActiveMQ消息特性:延迟和定时消息投递(Delay and Schedule Message Delivery) 转自:http://blog.csdn.net/kimmking/article/details/8443872 有时候我们不希望消息马上被broker投递出去,而是想要消息60秒以后发给消费者,或者我们想让消息没隔一定时间投递一次,一共投递指定的次数。。。 类似

梳理2024年,螺丝钉们爱用的3款剪辑软件

这年头,视频到处都是,就跟天上的星星一样数不清。不管你是公司里的新面孔,还是职场上的老狐狸,学会怎么剪视频,就好比找到了赢的秘诀。不管是给上司汇报工作,展示你的产品,还是自己搞点小视频记录生活,只要是剪辑得漂亮,肯定能一下子吸引大家的目光,让人记得你。咱们今天就来侃侃现在超火的三款视频剪辑工具,尤其是PR剪辑,你肯定听说过,这货在剪辑界可是大名鼎鼎,用它剪视频,既专业又麻利。 NO1. 福昕轻松

FreeRTOS学习笔记(二)任务基础篇

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、 任务的基本内容1.1 任务的基本特点1.2 任务的状态1.3 任务控制块——任务的“身份证” 二、 任务的实现2.1 定义任务函数2.2 创建任务2.3 启动任务调度器2.4 任务的运行与切换2.4.1 利用延时函数2.4.2 利用中断 2.5 任务的通信与同步2.6 任务的删除2.7 任务的通知2

Flink任务重启策略

概述 Flink支持不同的重启策略,以在故障发生时控制作业如何重启集群在启动时会伴随一个默认的重启策略,在没有定义具体重启策略时会使用该默认策略。如果在工作提交时指定了一个重启策略,该策略会覆盖集群的默认策略默认的重启策略可以通过 Flink 的配置文件 flink-conf.yaml 指定。配置参数 restart-strategy 定义了哪个策略被使用。常用的重启策略: 固定间隔 (Fixe

【Python知识宝库】上下文管理器与with语句:资源管理的优雅方式

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、什么是上下文管理器?二、上下文管理器的实现三、使用内置上下文管理器四、使用`contextlib`模块五、总结 前言 在Python编程中,资源管理是一个重要的主题,尤其是在处理文件、网络连接和数据库