应用场景:
cron表达式其实就是一个字符串,通过cron表达式可以定义任务触发的时间。
构成规则:分为6或7个域,由空格分隔,每个域代表一个含义。
每个域的含义分别为:秒、分钟、小时、日、月、周、年(可选)。
秒 分钟 小时 日 月 周 年
2022年10月12日上午9点整对应的cron表达式为:0 0 9 12 10 ? 2022
。
cron表达式在线生成器:Cron在线生成器 | 程序员导航网
@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 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 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 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——一次握手,两者之间就可以建立持久性的连接,并进行双向数据传输。
请求-响应结构:
无持续连接:
安全和缓存:
简单性:
实时双向通信:
低延迟和高频率数据传输:
高效数据传输:
无需频繁连接和断开:
导入坐标
org.springframework.boot
spring-boot-starter-websocket
导完坐标之后新建配置类,使WebSocket的第三方bean由ioc容器管理
@Configuration
public class WebSocketConfiguration {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
添加websocket的实体类
/**
* WebSocket服务
*/
@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {
//存放会话对象
private static Map 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 sessions = sessionMap.values(); // 获取所有客户端会话
for (Session session : sessions) { // 遍历每个会话
try {
// 服务器向客户端发送消息
session.getBasicRemote().sendText(message); // 发送文本消息
} catch (Exception e) {
e.printStackTrace(); // 捕获并打印异常
}
}
}
}
苍穹外卖遇到问题(包括跳过微信支付、nodejs不兼容等)-CSDN博客
/**
* 订单支付
* @param ordersPaymentDTO
* @return
*/
public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
// 当前登录用户id
Long 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 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响应给管理端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通信通常是由前端负责打开和关闭的,一旦连接建立,前端和后端可以通过这个通道双向发送和接收消息。
// 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));
}