設定 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)需要 JobRepositoryJobRepository 的配置透過 Java 配置 處理。

前面的範例說明了一個包含三個 Step 實例的 Job。與 Job 相關的建構器也可以包含其他有助於平行化 (Split)、宣告式流程控制 (Decision) 和流程定義外部化 (Flow) 的元素。

Job 介面有多種實作方式。但是,命名空間抽象化了配置中的差異。它只有三個必要的依賴項:名稱、JobRepositoryStep 實例列表。以下範例建立了一個 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 配置 的章節。XML 命名空間預設引用 idjobRepository 的 repository,這是一個合理的預設值。但是,您可以明確地覆蓋此預設值

<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 上設定 listeners,將 JobListeners 新增到 SimpleJob

  • Java

  • XML

以下範例示範如何在 Java job 定義中新增 listener 方法

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

以下範例示範如何在 XML job 定義中新增 listener 元素

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 定義,僅定義了 listeners 列表。Job (job1) 是一個具體的定義,它從 baseJob 繼承 listeners 列表,並將其與自己的 listeners 列表合併,以產生一個具有兩個 listeners 和一個 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>

有關更多詳細資訊,請參閱關於 從父 Step 繼承 的章節。

JobParametersValidator

在 XML 命名空間中宣告或使用 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 定義。