【苍穹外卖 | 项目日记 】第五天

今日完成的任务:

看了外卖关于微信支付的部分,跟着大佬改了下代码,跳过了微信支付功能

学习了SpringTask部分,处理了支付超时的订单和一直派送的订单。

以下是对SpringTask的一些介绍及应用

一、SpringTask 是什么?核心优势有哪些?

1. 核心定义

SpringTask 是 Spring 框架内置的定时任务调度框架,它封装了 JDK 原生的定时任务 API(Timer/TimerTask 等),提供了更简洁、更灵活的定时任务配置方式,支持基于注解和 XML 两种配置形式,目前主流项目中均以注解配置为主。

2. 核心优势

  • 轻量级无依赖:无需引入 Quartz 等第三方组件,直接集成在 Spring/Spring Boot 中,降低项目耦合度和部署复杂度;
  • 配置简单高效:注解一键开启,几行代码即可实现定时任务,学习成本极低;
  • 支持灵活表达式:基于 Cron 表达式,可满足几乎所有定时场景(固定频率、固定时间、周期性执行等);
  • 与 Spring 生态无缝集成:可直接注入 Service、Mapper 等 Spring Bean,无需额外处理依赖注入问题。

二、SpringTask 快速入门:3 步实现基础定时任务

我们以 Spring Boot 项目为例,快速搭建一个基础定时任务,步骤简单到难以置信:

步骤 1:开启定时任务支持

在 Spring Boot 主启动类上添加 @EnableScheduling 注解,开启定时任务调度功能:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling // 开启SpringTask定时任务支持
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

步骤 2:创建定时任务类

创建一个普通的 Spring 组件(添加 @Component 注解),用于存放定时任务方法。

步骤 3:编写定时任务方法

在方法上添加 @Scheduled 注解,指定定时规则,即可实现定时执行:

import org.springframework.stereotype.Component;
import org.springframework.scheduling.annotation.Scheduled;
import java.time.LocalDateTime;

@Component
public class BasicTimerTask {

    // 每5秒执行一次(固定频率)
    @Scheduled(fixedRate = 5000)
    public void fixedRateTask() {
        System.out.println("固定频率任务执行:" + LocalDateTime.now());
    }

    // 基于Cron表达式:每天凌晨1点执行
    @Scheduled(cron = "0 0 1 * * ?")
    public void cronTask() {
        System.out.println("Cron表达式任务执行:" + LocalDateTime.now());
    }
}

关键注解说明

  • @EnableScheduling:全局开启定时任务调度,必须添加在主启动类或配置类上;
  • @Scheduled:标记单个定时任务方法,支持多种定时规则配置:
    • fixedRate:固定频率执行,以上一次任务开始时间为基准,间隔指定毫秒后执行下一次;
    • fixedDelay:固定延迟执行,以上一次任务结束时间为基准,间隔指定毫秒后执行下一次;
    • cron:最灵活的配置方式,支持 Cron 表达式,满足复杂定时场景(后续重点讲解)。

三、核心知识点:Cron 表达式

Cron 表达式是 SpringTask 实现复杂定时的核心,我们无需死记硬背,掌握其结构和常用示例即可。

1. Cron 表达式结构

SpringTask 支持的是 6 位 Cron 表达式(秒、分、时、日、月、周),部分场景支持 7 位(年,可选,一般省略),格式如下:

plaintext

秒   分   时   日   月   周
0    0    1    *    *    ?   (每天凌晨1点执行)

2. 常用通配符说明

  • *:匹配所有值,比如 “秒” 位填*,表示每秒都执行;
  • ?:仅用于 “日” 和 “周” 位,标识不指定值,避免日和周的冲突(核心:二者只能有一个指定具体值,另一个用?);
  • -:表示范围,比如 “分” 位填10-20,表示 10 分到 20 分之间,每分钟执行一次;
  • ,:表示枚举值,比如 “时” 位填9,18,表示每天 9 点和 18 点各执行一次;
  • /:表示步长,比如 “秒” 位填0/5,表示从 0 秒开始,每 5 秒执行一次(等同于5,10,15...)。

3. 高频实用示例

Cron 表达式含义
0 0 1 * * ?每天凌晨 1 点执行
0 30 18 * * ?每天下午 6 点 30 分执行
0 0 9,18 * * ?每天 9 点和 18 点各执行一次
0 0/30 9-18 * * ?每天 9 点到 18 点,每 30 分钟执行一次
0 0 1 ? * 1每周一凌晨 1 点执行
0 0 1 1 * ?每月 1 号凌晨 1 点执行

四、SpringTask 在苍穹外卖中的实战应用

苍穹外卖是一个典型的餐饮外卖后台管理系统,其中存在多个需要定时执行的业务场景,SpringTask 在这里发挥了重要作用,以下是两个核心实战场景:

场景 1:定时处理 “超时未支付” 订单

业务背景

用户在苍穹外卖下单后,通常有 15 分钟的支付时间,如果 15 分钟内未支付,订单需要自动取消,同时释放对应库存(比如菜品库存、套餐库存),避免影响其他用户下单。

技术实现(SpringTask)
  1. 核心思路:每隔一定时间(比如 1 分钟),查询数据库中 “待支付” 状态且超过 15 分钟未支付的订单,批量执行取消操作;
  2. 代码实现:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.sky.service.OrderService;
import java.time.LocalDateTime;

@Component
public class OrderTimeoutTask {

    @Autowired
    private OrderService orderService; // 注入订单业务层

    // 每1分钟执行一次,清理超时未支付订单
    @Scheduled(fixedRate = 60 * 1000) 
    public void cancelTimeoutOrder() {
        // 1. 计算超时时间:当前时间往前推15分钟
        LocalDateTime timeoutTime = LocalDateTime.now().minusMinutes(15);
        // 2. 调用业务层方法,批量取消“待支付”且创建时间早于timeoutTime的订单
        orderService.cancelTimeoutOrders(timeoutTime);
        System.out.println("定时任务:清理超时未支付订单完成,执行时间:" + LocalDateTime.now());
    }
}
  1. 说明:此处使用fixedRate = 60 * 1000(每 1 分钟执行),而非 Cron 表达式,因为业务需要高频轮询,固定频率更贴合需求;同时,通过注入OrderService,直接调用业务逻辑,无需额外处理数据库连接等问题,体现了 SpringTask 与 Spring 生态的无缝集成。

场景 2:定时统计 “每日经营数据”

业务背景

苍穹外卖的商家需要查看每日经营报表(比如当日订单数、营业额、客单价等),这些数据需要自动统计,无需人工触发,通常在每天凌晨(比如 2 点,业务低峰期)执行统计,生成次日可查看的经营数据。

技术实现(SpringTask)
  1. 核心思路:每天凌晨 2 点,统计前一天的所有订单数据,计算经营指标,并存入经营报表表中,供前端展示;
  2. 代码实现:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.sky.service.ReportService;
import java.time.LocalDate;

@Component
public class BusinessReportTask {

    @Autowired
    private ReportService reportService; // 注入报表业务层

    // 每天凌晨2点执行,统计前一天的经营数据
    @Scheduled(cron = "0 0 2 * * ?") 
    public void generateBusinessReport() {
        // 1. 获取前一天的日期
        LocalDate yesterday = LocalDate.now().minusDays(1);
        // 2. 调用业务层方法,统计并生成经营报表
        reportService.generateBusinessReport(yesterday);
        System.out.println("定时任务:生成" + yesterday + "经营报表完成");
    }
}
  1. 说明:此处使用 Cron 表达式 0 0 2 * * ?(每天凌晨 2 点执行),因为业务需要固定时间点执行,且执行频率低(每天一次),Cron 表达式更贴合需求;选择凌晨 2 点而非 1 点,是为了避开其他定时任务的执行高峰,减少系统资源竞争。

场景 3:可选扩展:定时清理 “无效用户反馈”

除了上述核心场景,苍穹外卖还可通过 SpringTask 定时清理超过 30 天的已处理用户反馈,释放数据库存储空间,实现思路与上述一致,只需配置对应的 Cron 表达式和业务逻辑即可。

五、总结

  1. SpringTask 是 Spring 内置的轻量级定时任务框架,无需第三方依赖,配置简单,支持注解和 Cron 表达式;
  2. 核心注解:@EnableScheduling(开启定时)、@Scheduled(标记任务),关键配置:fixedRate(固定频率)、fixedDelay(固定延迟)、cron(复杂定时);
  3. Cron 表达式 6 位结构(秒、分、时、日、月、周),掌握常用通配符和示例即可满足大部分业务需求;
  4. 苍穹外卖中,SpringTask 主要用于超时订单自动取消每日经营数据统计等场景,贴合实际业务,提升系统自动化程度。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值