
本文介绍使用 spring 的 @scheduled 注解配合 cron 表达式,实现每日固定时刻(如 21:00)自动执行 java 方法;支持时区配置,并具备任务错过执行后的自然恢复能力(即不补执行,仅按日历周期触发)。
本文介绍使用 spring 的 @scheduled 注解配合 cron 表达式,实现每日固定时刻(如 21:00)自动执行 java 方法;支持时区配置,并具备任务错过执行后的自然恢复能力(即不补执行,仅按日历周期触发)。
在 Spring Boot 应用中,若需让某个业务方法(例如每日生成统计报表、清理过期缓存或发送定时通知)在每天特定时间自动运行,推荐使用 @Scheduled 注解——它轻量、声明式、与 Spring 生命周期深度集成,且天然支持时区与容错语义。
✅ 基础配置步骤
-
启用定时任务支持:在主启动类或任意
@Configuration类上添加@EnableScheduling:
@SpringBootApplication
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}-
在目标方法上添加
@Scheduled:确保该方法是public、无参数、返回void,并位于 Spring 管理的 Bean 中(如@Service或@Component):
@Service
public class DailyTaskService {
@Scheduled(cron = "0 0 0 * * ?", zone = "Asia/Shanghai") // 每天 00:00:00 执行
public void executeDailyJob() {
System.out.println("✅ Daily job executed at " + LocalDateTime.now());
// 此处放置你的业务逻辑,如数据库操作、HTTP 调用等
}
}? Cron 表达式说明(Quartz 格式,6 位):
秒 分 时 日 月 周 [年]→"0 0 0 * * ?"表示“每天 00:00:00”,?表示不指定具体星期(避免与“日”冲突);zone = "Asia/Shanghai"显式指定时区,防止服务器系统时区不一致导致偏差。
⚠️ 关键注意事项
-
不支持“补执行”:Spring 默认
@Scheduled是基于日历周期触发(fixed-rate / fixed-delay / cron),而非“错过即补”。若应用在设定时间未运行(如服务宕机、机器休眠),该次任务将被跳过,下一次仍严格按 cron 规则在次日同一时刻执行——这正符合你“若时间错过则次日执行”的需求。 -
必须启用
@EnableScheduling:缺少该注解会导致@Scheduled完全失效,且无任何报错提示。 -
方法不能是
static或private:Spring AOP 代理机制要求方法可被代理,仅public实例方法有效。 - 避免长时间阻塞:若任务执行耗时过长(如 >1 分钟),建议异步处理或增加超时控制,防止影响后续调度。
? 进阶建议
- 若需更灵活的动态调度(如运行时修改执行时间),可结合
TaskScheduler编程式注册Runnable; - 对于高可用场景,建议配合分布式锁(如 RedisLock)或外部调度中心(如 XXL-JOB、Elastic Job),避免多实例重复执行;
- 生产环境务必添加日志与异常捕获,防止静默失败:
@Scheduled(cron = "0 0 21 * * ?", zone = "Europe/Paris")
public void sendEveningReport() {
try {
reportService.generateAndSend();
} catch (Exception e) {
log.error("❌ Failed to execute daily evening report", e);
// 可选:触发告警(邮件/SMS)
}
}通过以上配置,你即可实现稳定、可维护、符合生产规范的每日定时任务。无需额外依赖 Quartz,开箱即用,精准可控。


















