配置 Job
`Job` 介面有多種實現。然而,這些實現被抽象在提供的構建器(用於 Java 配置)或 XML 名稱空間(用於基於 XML 的配置)之後。以下示例展示了 Java 和 XML 配置
-
Java
-
XML
@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.start(playerLoad())
.next(gameLoad())
.next(playerSummarization())
.build();
}
一個 `Job`(通常包括其中的任何 `Step`)需要一個 `JobRepository`。`JobRepository` 的配置透過 `Java 配置` 來處理。
前面的示例展示了一個包含三個 `Step` 例項的 `Job`。Job 相關的構建器還可以包含其他元素,有助於並行化 (`Split`)、宣告式流程控制 (`Decision`) 以及流程定義的外部化 (`Flow`)。
`Job` 介面有多種實現。然而,名稱空間抽象了配置的差異。它只有三個必需的依賴:一個名稱、`JobRepository` 和 `Step` 例項列表。以下示例建立了一個 `footballJob`
<job id="footballJob">
<step id="playerload" parent="s1" next="gameLoad"/>
<step id="gameLoad" parent="s2" next="playerSummarization"/>
<step id="playerSummarization" parent="s3"/>
</job>
前面的示例使用父 Bean 定義來建立 Step。有關內聯宣告特定 Step 詳細資訊的更多選項,請參閱 step configuration 部分。XML 名稱空間預設引用 `id` 為 `jobRepository` 的倉庫,這是一個合理的預設值。但是,你可以顯式覆蓋此預設值
<job id="footballJob" job-repository="specialRepository">
<step id="playerload" parent="s1" next="gameLoad"/>
<step id="gameLoad" parent="s3" next="playerSummarization"/>
<step id="playerSummarization" parent="s3"/>
</job>
除了 Step 之外,Job 配置還可以包含其他有助於並行化 (`<split>`)、宣告式流程控制 (`<decision>`) 和流程定義外部化 (`<flow/>`) 的元素。
可重啟性
執行批處理 Job 時的一個關鍵問題是 `Job` 在重啟時的行為。如果特定 `JobInstance` 的 `JobExecution` 已存在,則啟動 `Job` 被視為“重啟”。理想情況下,所有 Job 都應該能夠在上次中斷的地方繼續執行,但在某些情況下這不可能。在這種情況下,完全由開發者負責確保建立新的 `JobInstance`。 但是,Spring Batch 提供了一些幫助。如果一個 `Job` 不應被重啟,而應始終作為新的 `JobInstance` 的一部分執行,則可以將 `restartable` 屬性設定為 `false`。
-
Java
-
XML
以下示例展示瞭如何在 Java 中將 `restartable` 欄位設定為 `false`
@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.preventRestart()
...
.build();
}
以下示例展示瞭如何在 XML 中將 `restartable` 欄位設定為 `false`
<job id="footballJob" restartable="false">
...
</job>
換句話說,將 `restartable` 設定為 `false` 意味著“此 `Job` 不支援再次啟動”。重啟一個不可重啟的 `Job` 會導致丟擲 `JobRestartException` 異常。以下 Junit 程式碼會導致丟擲該異常
Job job = new SimpleJob();
job.setRestartable(false);
JobParameters jobParameters = new JobParameters();
JobExecution firstExecution = jobRepository.createJobExecution(job, jobParameters);
jobRepository.saveOrUpdate(firstExecution);
try {
jobRepository.createJobExecution(job, jobParameters);
fail();
}
catch (JobRestartException e) {
// expected
}
首次為不可重啟的 Job 建立 `JobExecution` 不會導致問題。然而,第二次嘗試會丟擲 `JobRestartException` 異常。
攔截 Job 執行
在 `Job` 執行過程中,可能需要在其生命週期的各個事件發生時收到通知,以便執行自定義程式碼。`SimpleJob` 透過在適當時候呼叫 `JobListener` 來實現這一點
public interface JobExecutionListener {
void beforeJob(JobExecution jobExecution);
void afterJob(JobExecution jobExecution);
}
你可以透過在 Job 上設定監聽器來向 `SimpleJob` 新增 `JobListeners`。
-
Java
-
XML
以下示例展示瞭如何向 Java Job 定義新增監聽器方法
@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.listener(sampleListener())
...
.build();
}
以下示例展示瞭如何向 XML Job 定義新增監聽器元素
<job id="footballJob">
<step id="playerload" parent="s1" next="gameLoad"/>
<step id="gameLoad" parent="s2" next="playerSummarization"/>
<step id="playerSummarization" parent="s3"/>
<listeners>
<listener ref="sampleListener"/>
</listeners>
</job>
請注意,無論 `Job` 成功還是失敗,都會呼叫 `afterJob` 方法。如果你需要確定成功或失敗,可以從 `JobExecution` 中獲取該資訊
public void afterJob(JobExecution jobExecution){
if (jobExecution.getStatus() == BatchStatus.COMPLETED ) {
//job success
}
else if (jobExecution.getStatus() == BatchStatus.FAILED) {
//job failure
}
}
與此介面對應的註解是
-
@BeforeJob
-
@AfterJob
繼承自父 Job
如果一組 Job 共享相似但不完全相同的配置,則可以定義一個“父” `Job`,具體的 `Job` 例項可以從中繼承屬性。類似於 Java 中的類繼承,“子” `Job` 將其元素和屬性與父級合併。
在以下示例中,`baseJob` 是一個抽象的 `Job` 定義,僅定義了一個監聽器列表。`Job` (`job1`) 是一個具體定義,它繼承了 `baseJob` 的監聽器列表,並與自己的監聽器列表合併,從而產生一個具有兩個監聽器和一個 `Step` (`step1`) 的 `Job`。
<job id="baseJob" abstract="true">
<listeners>
<listener ref="listenerOne"/>
</listeners>
</job>
<job id="job1" parent="baseJob">
<step id="step1" parent="standaloneStep"/>
<listeners merge="true">
<listener ref="listenerTwo"/>
</listeners>
</job>
有關更詳細的資訊,請參閱 Inheriting from a Parent Step 部分。
JobParametersValidator
在 XML 名稱空間中宣告的 Job 或使用 `AbstractJob` 的任何子類的 Job 都可以選擇在執行時宣告 Job 引數的驗證器。當例如需要斷言 Job 以所有強制引數啟動時,這非常有用。有一個 `DefaultJobParametersValidator`,你可以使用它來約束簡單的強制和可選引數的組合。對於更復雜的約束,你可以自己實現該介面。
-
Java
-
XML
驗證器的配置透過 Java 構建器支援
@Bean
public Job job1(JobRepository jobRepository) {
return new JobBuilder("job1", jobRepository)
.validator(parametersValidator())
...
.build();
}
驗證器的配置透過 XML 名稱空間中的 Job 子元素支援,如下例所示
<job id="job1" parent="baseJob3">
<step id="step1" parent="standaloneStep"/>
<validator ref="parametersValidator"/>
</job>
你可以將驗證器指定為引用(如前面所示),或作為 `beans` 名稱空間中的巢狀 bean 定義。