需求分析:
主要针对两种情况
1、下单后一直处于”未支付“状态
2、用户收货后未点完成按钮,订单一直处于“派送中”状态
解决:
情况1:
通过定时任务每分钟检查一次是否存在支付超时的订单,如果超过15分钟未支付则修改订单状态为取消
情况2:
通过定时任务每天1点检查一次是否存在"派送中"的订单,如果存在则修改为已完成
使用技术:
SpingTask框架,该框架底层是使用JDK提供的定时任务工具类Timer和TimerTask,通过线程池利用线程来运行每个定时任务,因此不要随意乱用定时任务,会造成线程资源耗尽性能过慢
大致流程:
1、在启动类上添加@EnableScheduling
2、创建自定义定时任务类,添加到IOC容器
3、在定时任务方法上方添加@Scheduled ( cron = "这里设置cron表达式" )
首先来看下处理两种情况需要共有的Mapper
<update id="updateStatusByIds">
update orders
<set>
<if test="status != null">
status = #{status}
</if>
</set>
where id in
<foreach collection="ordersArrayList" item="orderId" separator="," open="(" close=")">
#{orderId}
</foreach>
</update>
<select id="selectByStatusAndOrderTime" resultType="com.sky.entity.Orders">
select * from orders
<where>
<if test="status != null">
status = #{status}
</if>
<if test="checkTime != null">
and order_time <= #{checkTime}
</if>
</where>
</select>
说明:
selectByStatusAndOrderTime 的功能是通过订单状态和传入的时间查找超时的订单
updateStatusByIds 的功能是将符合条件的订单状态修改
注意 :
order_time & lt ; = #{checkTime}表示 order_time <= #{checkTime}
> 则表示 >
处理下单后订单一直处于未支付状态
/**
* 将超时未支付订单状态改为取消
* 1、每分钟检查一次
* 2、检测订单状态为未支付且超过下单时间15分钟的订单
* 3、将符合条件的订单状态修改为已取消
*/
@Scheduled(cron = "0 * * * * ?")
public void cancelOrder(){
//获取到15分钟前的时间
LocalDateTime checkTime = LocalDateTime.now().minusMinutes(15);
//根据订单状态和15分钟前时间查询未支付且超时了的订单
List<Orders> ordersList = orderMapper.selectByStatusAndOrderTime(Orders.PENDING_PAYMENT,checkTime);
//将这些订单的id统一存入一个集合
if(ordersList != null && ordersList.size() > 0){
ArrayList<Long> ordersArrayList = new ArrayList<>();
for (Orders orders : ordersList) {
ordersArrayList.add(orders.getId());
}
//通过ids将这些订单状态修改为取消
orderMapper.updateStatusByIds(ordersArrayList,Orders.CANCELLED);
log.info("处理了{}份超时订单",ordersList.size());
}else{
log.info("没有超时订单");
}
}
这里不做过多说明,注解中有详细解释
处理前一天派送中的订单
/**
* 每天凌晨1点检查一次,将在配送中的订单状态改为已完成
* 获取到前一天的所有状态为配送中的订单
*/
@Scheduled(cron = "0 0 1 * * ?")
public void completeOrder(){
LocalDateTime yesterday = LocalDateTime.now().minusHours(1);
List<Orders> orders = orderMapper.selectByStatusAndOrderTime(Orders.DELIVERY_IN_PROGRESS, yesterday);
if(orders != null && orders.size()>0) {
ArrayList<Long> ids = new ArrayList<>();
for (Orders order : orders) {
ids.add(order.getId());
}
orderMapper.updateStatusByIds(ids, Orders.COMPLETED);
log.info("处理了{}份前一天配送的订单",orders.size());
}
log.info("前一天配送的订单已全部完成");
}
同样的这里使用到的逻辑和上一个类似,只是条件和cron表达式变化了一下