配置 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`

Java 配置
@Bean
public Job footballJob(JobRepository jobRepository) {
    return new JobBuilder("footballJob", jobRepository)
                     .preventRestart()
                     ...
                     .build();
}

以下示例展示瞭如何在 XML 中將 `restartable` 欄位設定為 `false`

XML 配置
<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 定義新增監聽器方法

Java 配置
@Bean
public Job footballJob(JobRepository jobRepository) {
    return new JobBuilder("footballJob", jobRepository)
                     .listener(sampleListener())
                     ...
                     .build();
}

以下示例展示瞭如何向 XML Job 定義新增監聽器元素

XML 配置
<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 定義。