JavaWeb(苍穹外卖)--学习笔记16(定时任务工具Spring Task,Cron表达式)

发布于:2025-08-02 ⋅ 阅读:(13) ⋅ 点赞:(0)

前言

本篇文章是学习B站黑马程序员苍穹外卖的学习笔记📑。我的学习路线是Java基础语法-JavaWeb-做项目,管理端的功能学习完之后,就进入到了用户端微信小程序的开发,用户端开发的流程大致为用户登录—商品浏览(其中涉及到缓存,之前写过)—添加/查看/清空购物车—下单支付(到现在没搞懂😵‍💫)—地址簿—订单查询/超时/取消处理(巨多)…还有我没学到的🤪🤪

从订单支付这里,一直到day10,要不是很难的看不懂的,要不就是一些之前学过的,我是直接根据课程资料将代码导入,然后稍微看了看逻辑(太多太难了边学边做总结吧)。

🤔如果用户下单但一直不支付,这时就需要我们设置一定的时间,定时清理掉(既然不给钱,那我直接把你轰出去😡)。

🔍下面来看看订单状态定时处理功能的开发

1. 🙌先来了解一下Spring Task 和 Tack_cron表达式

Spring Task 是 Spring 框架提供的一个轻量级的任务调度模块,它允许你在 Spring 应用中简单地配置和执行定时任务。使用 Spring Task,你可以通过注解或者 XML 配置的方式定义定时任务,无需引入额外的库或依赖复杂的配置。(这个是ai给我的概念,我看着也有点懵🤪)

✅你可以把它理解成 手机里的“闹钟”App,只不过它是给你的 Java 程序用的。

你想让程序:每次下单后15分支不付款,就清除订单
只要告诉 Spring Task:“到时间就帮我做这件事”,它就会乖乖地按时执行。

cron表达式是一个字符串,通过cron表达式可以定义任务触发的时间。
一条 cron 任务的基本格式如下:

┌───────────── 分钟 (0 - 59)
│ ┌──────────── 小时 (0 - 23)
│ │ ┌───────────── 日期 (1 - 31)
│ │ │ ┌────────────── 月份 (1 - 12)
│ │ │ │ ┌─────────────── 星期几 (0 - 6)07 都表示周日)
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
*   *   *   *   *   要执行的命令

常用符号说明:

在这里插入图片描述
🙌例:
0 0 * * * /backup.sh :每天零点执行 /backup.sh

*/10 * * * * /ping.sh:每 10 分钟执行一次

30 8 * * 1-5 /check.log:周一到周五早上 8:30 执行

✨注:可以直接用工具生成(更方便):奇Q在线Cron表达式生成器

2. 下面来举个例子来看看它是怎么使用的

①导入maven

启动类添加注解@EnableScheduling开启任务调度

③自定义定时任务类

package com.sky.task;
...
/**
 * 自定义定时任务
 */

@Component
@Slf4j
public class MyTask {

    /**
     * 定时任务1
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void executeTask(){
        log.info("定时任务1开始执行:{}", new Date());
    }

}

运行后:控制台每5秒输出一次
在这里插入图片描述

🧠最后来看看在实际项目中怎么使用:

先来看看要实现的功能:

  1. 处理超时订单:15分钟未支付,取消订单
  2. 每天凌晨1点处理一直处于派送中的订单

🔍✌️下面来看看代码:
就是结合刚刚学的内容,多加了两个注解和一个 select 语句(查询符合条件的订单再对其进行更改):

在sky-server的task包(P125创建的)下创建一个OrderTask类:

package com.sky.task;
...

/**
 * 订单定时任务
 */

@Component
@Slf4j
public class OrderTask {

    @Autowired
    private OrderMapper orderMapper;

    /**
     * 处理超时订单
     *
     */

    @Scheduled(cron = "0 * * * * ? ") // 每分钟执行一次
    //@Scheduled(cron = "1/5 * * * * ?")
    public void processTimeOutOrder(){
        log.info(" 定时处理超时订单:{}", LocalDateTime.now());

        LocalDateTime time = LocalDateTime.now().plusMinutes(-15);

        List<Orders> orderList = orderMapper.getByStatusAndOrderTimeLT(Orders.PENDING_PAYMENT, time);

        if(orderList != null && orderList.size() > 0){
            for (Orders orders : orderList) {
                orders.setStatus(Orders.CANCELLED);
                orders.setCancelReason("支付超时,自动取消");
                orders.setCancelTime(LocalDateTime.now());
                orderMapper.update(orders);
            }
        }

    }

    /**
     * 处理一直处于派送中状态的订单
     */
    @Scheduled(cron = "0 0 1 * * ? ")//每日凌晨1点执行一次
    //@Scheduled(cron = "0/5 * * * * ?")
    public void processDeliveringOrder(){
        log.info("定时处理支付超时订单:{}", LocalDateTime.now());

        List<Orders> orderList =orderMapper.getByStatusAndOrderTimeLT(Orders.DELIVERY_IN_PROGRESS, LocalDateTime.now().plusMinutes(-60));

        if(orderList != null && orderList.size() > 0){
            for (Object orders : orderList) {
                Orders order = (Orders) orders;
                order.setStatus(Orders.COMPLETED);
                orderMapper.update(order);
            }
        }
    }

}

mapper包下的OrderMapper:

 /**
     * 统计指定时间区间内订单数量
     * @param status
     * @param orderTime
     */
    @Select("select * from orders where status = #{status} and order_time < #{orderTime}")
    List<Orders> getByStatusAndOrderTimeLT (Integer status, LocalDateTime orderTime);


    /**
     * 修改订单信息
     * @param orders
     */
    void update(Orders orders);//这个语句有点长,放到其对应XML文件中了

<update id="update" parameterType="Orders">
        update orders
        <set>
            <if test="number != null"> number=#{number}, </if>
            <if test="status != null"> status=#{status}, </if>
            <if test="addressBookId != null"> address_book_id=#{addressBookId}, </if>
            <if test="orderTime != null"> order_time=#{orderTime},</if>
            <if test="checkoutTime != null"> checkout_time=#{checkoutTime}, </if>
            <if test="payMethod != null"> pay_method=#{payMethod}, </if>
            <if test="payStatus != null"> pay_status=#{payStatus}, </if>
            <if test="amount != null"> amount=#{amount}, </if>
            <if test="remark != null"> remark=#{remark}, </if>
            <if test="phone != null"> phone=#{phone}, </if>
            <if test="address != null"> address=#{address}, </if>
            <if test="userName != null"> user_name=#{userName}, </if>
            <if test="consignee != null"> consignee=#{consignee} ,</if>
            <if test="cancelReason != null"> cancel_reason=#{cancelReason}, </if>
            <if test="rejectionReason != null"> rejection_reason=#{rejectionReason}, </if>
            <if test="cancelTime != null"> cancel_time=#{cancelTime}, </if>
            <if test="estimatedDeliveryTime != null"> estimated_delivery_time=#{estimatedDeliveryTime}, </if>
            <if test="deliveryStatus != null"> delivery_status=#{deliveryStatus}, </if>
            <if test="deliveryTime != null"> delivery_Time=#{deliveryTime}, </if>
            <if test="packAmount != null"> pack_amount=#{packAmount},</if>
            <if test="tablewareNumber != null"> tableware_number=#{tablewareNumber}, </if>
            <if test="tablewareStatus != null"> tableware_status=#{tablewareStatus}, </if>
        </set>
        where id=#{id}
    </update>

小白啊!!!写的不好轻喷啊🤯如果觉得写的不好,点个赞吧🤪(批评是我写作的动力)

…。。。。。。。。。。。…请添加图片描述

…。。。。。。。。。。。…