今日完成的任务:
看了外卖关于微信支付的部分,跟着大佬改了下代码,跳过了微信支付功能
学习了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 分钟),查询数据库中 “待支付” 状态且超过 15 分钟未支付的订单,批量执行取消操作;
- 代码实现:
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());
}
}
- 说明:此处使用
fixedRate = 60 * 1000(每 1 分钟执行),而非 Cron 表达式,因为业务需要高频轮询,固定频率更贴合需求;同时,通过注入OrderService,直接调用业务逻辑,无需额外处理数据库连接等问题,体现了 SpringTask 与 Spring 生态的无缝集成。
场景 2:定时统计 “每日经营数据”
业务背景
苍穹外卖的商家需要查看每日经营报表(比如当日订单数、营业额、客单价等),这些数据需要自动统计,无需人工触发,通常在每天凌晨(比如 2 点,业务低峰期)执行统计,生成次日可查看的经营数据。
技术实现(SpringTask)
- 核心思路:每天凌晨 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 + "经营报表完成");
}
}
- 说明:此处使用 Cron 表达式
0 0 2 * * ?(每天凌晨 2 点执行),因为业务需要固定时间点执行,且执行频率低(每天一次),Cron 表达式更贴合需求;选择凌晨 2 点而非 1 点,是为了避开其他定时任务的执行高峰,减少系统资源竞争。
场景 3:可选扩展:定时清理 “无效用户反馈”
除了上述核心场景,苍穹外卖还可通过 SpringTask 定时清理超过 30 天的已处理用户反馈,释放数据库存储空间,实现思路与上述一致,只需配置对应的 Cron 表达式和业务逻辑即可。
五、总结
- SpringTask 是 Spring 内置的轻量级定时任务框架,无需第三方依赖,配置简单,支持注解和 Cron 表达式;
- 核心注解:
@EnableScheduling(开启定时)、@Scheduled(标记任务),关键配置:fixedRate(固定频率)、fixedDelay(固定延迟)、cron(复杂定时); - Cron 表达式 6 位结构(秒、分、时、日、月、周),掌握常用通配符和示例即可满足大部分业务需求;
- 苍穹外卖中,SpringTask 主要用于超时订单自动取消、每日经营数据统计等场景,贴合实际业务,提升系统自动化程度。

5409

被折叠的 条评论
为什么被折叠?



