<!-- quartz-1.8.5.jar, commons-collections-3.2.1.jar, commons-logging-1.1.jar -->
<beans xmlns:task="https://www.springframework.org/schema/task"
xsi:schemaLocation="...
https://www.springframework.org/schema/task https://www.springframework.org/schema/task/spring-task-3.1.xsd">
<task:annotation-driven/>
<context:component-scan base-package="com.test"/>
@Component
public class MyTestServiceImpl implements IMyTestService {
@Scheduled(cron = "0/5 * * * * ?") // 每 5 秒
@Override
public void myTest() {
System.out.println("進入測試");
}
}
注意:@Scheduled 方法不能有回傳值,類需標註 @Component。
| 表達式 | 含義 |
|---|---|
0 0 12 * * ? | 每天中午 12:00 |
0 15 10 ? * * | 每天 10:15 |
0 0/5 14 * * ? | 每天 14:00-14:55 每 5 分鐘 |
0 0/5 14,18 * * ? | 14:00-14:55 與 18:00-18:55 每 5 分鐘 |
0 15 10 ? * MON-FRI | 週一至週五 10:15 |
格式:秒 分 時 日 月 周 [年]
<bean id="myJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="jobs.MyJob"/>
</bean>
<bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="myJob"/>
<property name="cronExpression" value="0 0 2 * * ?"/> <!-- 每天凌晨 2 點 -->
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list><ref bean="myTrigger"/></list>
</property>
</bean>
核心:實作 TriggerListener,在 triggerComplete 中排程下一個任務。
public class NextJobTriggerListener extends TriggerListenerSupport {
private SimpleTriggerBean nextTrigger;
@Override
public void triggerComplete(Trigger trigger, JobExecutionContext context, int code) {
try {
Scheduler scheduler = context.getScheduler();
JobDetail nextJob = nextTrigger.getJobDetail();
Trigger oldTrigger = scheduler.getTrigger(nextTrigger.getName(), nextTrigger.getGroup());
if (oldTrigger == null) { // 避免重複排程
scheduler.scheduleJob(nextJob, nextTrigger);
}
} catch (Exception e) { e.printStackTrace(); }
}
}
<!-- 主任務 -->
<bean id="mainJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="jobs.MainJob"/>
</bean>
<bean id="mainTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="mainJob"/>
<property name="startDelay" value="6000"/> <!-- 啟動 6 秒後執行 -->
<property name="repeatInterval" value="3600000"/>
<property name="triggerListenerNames"><list><value>chainListener</value></list></property>
</bean>
<!-- 後續任務 -->
<bean id="secondJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="jobs.SecondJob"/>
</bean>
<bean id="secondTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="secondJob"/>
<property name="startDelay" value="6000"/>
<property name="repeatInterval" value="6000"/>
</bean>
<!-- 監聽器串聯 -->
<bean id="chainListener" class="listeners.NextJobTriggerListener">
<property name="nextTrigger" ref="secondTrigger"/>
<property name="name" value="chainListener"/>
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers"><list><ref bean="mainTrigger"/></list></property>
<property name="triggerListeners"><list><ref bean="chainListener"/></list></property>
</bean>
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX + 資料庫表jdbcjobstore 確保重啟不丟失排程org.quartz.threadPool.threadCount=20StatefulJob 防止並發執行,捕獲異常記錄日誌不拋出| 場景 | 推薦方式 |
|---|---|
| 簡單固定頻率、開發期 | @Scheduled 註解 |
| 複雜 Cron、需動態修改、生產環境 | XML JobDetail + Trigger |
| 任務依賴鏈、條件觸發 | TriggerListener + XML |
| 叢集高可用 | XML + JDBC JobStore |