实现定时任务可以使用spring家族中的sprinig-task;
spring-task是Spring框架的任务调度工具,可以按照约定的时间自动执行某个代码逻辑;
应用场景
cron表达式的使用
入门案例
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
@Component
@Slf4j
/**
* 自定义定时任务类
*/
public class MyTask {
//从第0秒开始,每隔5秒触发一次;
@Scheduled(cron = "0/5 * * * * ?")
public void executeTask(){
log.info("定时任务开始执行......"+ LocalDateTime.now());
}
}
用户下单之后可能存在
/**
* 处理超时订单,每分钟触发一次
*/
// @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);
}
}
}
/**
* 处理派送中订单,每天触发一次
*/
@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使用流程
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-websocketartifactId>
dependency>
/**
* WebSocket配置类,用于注册WebSocket的Bean
*/
@Configuration
public class WebSocketConfiguration {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
/**
* WebSocket服务
*/
@Component
@ServerEndpoint("/ws/{sid}") //websocket客户端请求路径;
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();
}
}
}
}
可能出现的问题
内网穿透工具cpolar
会得到你的令牌,复制之
进入到带有cpolar.exe的目录,打开命令行
windows下使用命令:
cpolar.exe authtoken 你的authtoken
会生成一个内网穿透的配置文件,文件的地址会给出:
然后可以临时启动一个服务指定一个IP地址:
cpolar.exe http 8080
此时生成了一个域名并被映射到localhost:8080,使用临时域名访问swagger接口文档(注意复制时如果cmd窗口无法复制,可以右键点击“标记”,在此之后便可以复制)
修改配置文件
由于前边使用的模拟微信支付,直接调用了支付成功的接口,所以并没有微信支付的相关配置;
wechat:
appid: 你的appid
secret: 你的appsecret
notify-url: https://21e88914.r24.cpolar.top/notify/paySuccess
refund-notify-url: https://21e88914.r24.cpolar.top/notify/refundSuccess
修改支付成功业务层代码OrderServiceImpl.paySuccess,这里代码中所指出的客户端是商家管理端(由于商家可能打开了多个管理端页面,所以向所有与websocket-server建立了连接的管理端都推送了订单通知)
/**
* 支付成功,修改订单状态
*
* @param outTradeNo
*/
public void paySuccess(String outTradeNo) {
// 当前登录用户id
Long 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);
}
/**
* 用户催单
* @param id
*/
@Override
public 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);
}