攔截 Step 執行

Job 一樣,在 Step 執行期間,使用者可能需要在許多事件中執行某些功能。例如,為了寫入需要頁尾的平面檔案,當 Step 完成時,需要通知 ItemWriter,以便可以寫入頁尾。這可以透過眾多 Step 範圍監聽器之一實現。

你可以透過 listeners 元素將實現 StepListener 擴充套件之一(但不是該介面本身,因為它為空)的任何類應用於步驟。listeners 元素在步驟、任務或塊宣告中有效。我們建議你將監聽器宣告在其功能適用的級別,或者,如果它是多功能的(例如 StepExecutionListenerItemReadListener),則將其宣告在其適用的最細粒度級別。

  • Java

  • XML

以下示例顯示了在 Java 中應用於塊級別的監聽器

Java 配置
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
	return new StepBuilder("step1", jobRepository)
				.<String, String>chunk(10).transactionManager(transactionManager)
				.reader(reader())
				.writer(writer())
				.listener(chunkListener())
				.build();
}

以下示例顯示了在 XML 中應用於塊級別的監聽器

XML 配置
<step id="step1">
    <tasklet>
        <chunk reader="reader" writer="writer" commit-interval="10"/>
        <listeners>
            <listener ref="chunkListener"/>
        </listeners>
    </tasklet>
</step>

如果使用名稱空間 <step> 元素或其中一個 *StepFactoryBean 工廠,則本身實現 StepListener 介面之一的 ItemReaderItemWriterItemProcessor 會自動註冊到 Step。這僅適用於直接注入 Step 的元件。如果監聽器巢狀在另一個元件中,則需要明確註冊它(如前所述,請參閱 註冊 ItemStreamStep)。

除了 StepListener 介面之外,還提供了註解來解決相同的問題。普通 Java 物件的方法可以使用這些註解,然後將其轉換為相應的 StepListener 型別。通常還會註解塊元件的自定義實現,例如 ItemReaderItemWriterTasklet。XML 解析器會分析 <listener/> 元素的註解,並在構建器中使用 listener 方法進行註冊,因此你只需使用 XML 名稱空間或構建器將監聽器註冊到步驟即可。

StepExecutionListener

StepExecutionListener 表示 Step 執行的最通用監聽器。它允許在 Step 開始之前和結束之後進行通知,無論它是正常結束還是失敗,如下例所示

public interface StepExecutionListener extends StepListener {

    void beforeStep(StepExecution stepExecution);

    ExitStatus afterStep(StepExecution stepExecution);

}

afterStep 的返回型別是 ExitStatus,以便讓監聽器有機會修改 Step 完成時返回的退出程式碼。

與此介面對應的註解是

  • @BeforeStep

  • @AfterStep

ChunkListener

“塊”定義為在事務範圍內處理的項。在每個提交間隔提交事務會提交一個塊。你可以使用 ChunkListener 在塊開始處理之前或塊成功完成之後執行邏輯,如下面的介面定義所示

public interface ChunkListener extends StepListener {

    void beforeChunk(ChunkContext context);
    void afterChunk(ChunkContext context);
    void afterChunkError(ChunkContext context);

}

beforeChunk 方法在事務啟動後但在 ItemReader 開始讀取之前呼叫。相反,afterChunk 在塊提交後呼叫(如果回滾則根本不呼叫)。

與此介面對應的註解是

  • @BeforeChunk

  • @AfterChunk

  • @AfterChunkError

當沒有塊宣告時,你可以應用 ChunkListenerTaskletStep 負責呼叫 ChunkListener,因此它也適用於非項導向的任務(它在任務之前和之後被呼叫)。

ChunkListener 不設計為丟擲受檢異常。錯誤必須在實現中處理,否則步驟將終止。

ItemReadListener

在前面討論跳過邏輯時,提到記錄跳過的記錄可能很有益,以便以後處理。在讀取錯誤的情況下,這可以透過 ItemReaderListener 完成,如下面的介面定義所示

public interface ItemReadListener<T> extends StepListener {

    void beforeRead();
    void afterRead(T item);
    void onReadError(Exception ex);

}

beforeRead 方法在每次呼叫 ItemReader 上的 read 之前呼叫。afterRead 方法在每次成功呼叫 read 之後呼叫,並傳遞已讀取的項。如果在讀取時發生錯誤,則呼叫 onReadError 方法。提供了遇到的異常,以便可以記錄它。

與此介面對應的註解是

  • @BeforeRead

  • @AfterRead

  • @OnReadError

ItemProcessListener

ItemReadListener 一樣,可以“監聽”項的處理,如下面的介面定義所示

public interface ItemProcessListener<T, S> extends StepListener {

    void beforeProcess(T item);
    void afterProcess(T item, S result);
    void onProcessError(T item, Exception e);

}

beforeProcess 方法在 ItemProcessor 上的 process 之前呼叫,並傳遞要處理的項。afterProcess 方法在項成功處理後呼叫。如果在處理時發生錯誤,則呼叫 onProcessError 方法。提供了遇到的異常和嘗試處理的項,以便可以記錄它們。

與此介面對應的註解是

  • @BeforeProcess

  • @AfterProcess

  • @OnProcessError

ItemWriteListener

你可以使用 ItemWriteListener “監聽”項的寫入,如下面的介面定義所示

public interface ItemWriteListener<S> extends StepListener {

    void beforeWrite(List<? extends S> items);
    void afterWrite(List<? extends S> items);
    void onWriteError(Exception exception, List<? extends S> items);

}

beforeWrite 方法在 ItemWriter 上的 write 之前呼叫,並傳遞要寫入的項列表。afterWrite 方法在項成功寫入後呼叫,但在提交與塊處理相關的事務之前。如果在寫入時發生錯誤,則呼叫 onWriteError 方法。提供了遇到的異常和嘗試寫入的項,以便可以記錄它們。

與此介面對應的註解是

  • @BeforeWrite

  • @AfterWrite

  • @OnWriteError

SkipListener

ItemReadListenerItemProcessListenerItemWriteListener 都提供了錯誤通知機制,但沒有一個會告知你記錄實際上已被跳過。例如,即使項被重試併成功,也會呼叫 onWriteError。因此,有一個單獨的介面用於跟蹤跳過的項,如下面的介面定義所示

public interface SkipListener<T,S> extends StepListener {

    void onSkipInRead(Throwable t);
    void onSkipInProcess(T item, Throwable t);
    void onSkipInWrite(S item, Throwable t);

}

每當在讀取時跳過項時,都會呼叫 onSkipInRead。應該注意的是,回滾可能會導致同一個項被多次註冊為跳過。在寫入時跳過項時,會呼叫 onSkipInWrite。由於該項已成功讀取(未跳過),因此也將其自身作為引數提供。

與此介面對應的註解是

  • @OnSkipInRead

  • @OnSkipInWrite

  • @OnSkipInProcess

跳過監聽器和事務

SkipListener 最常見的用例之一是記錄跳過的項,以便可以使用另一個批處理過程甚至人工過程來評估和修復導致跳過的問題。由於在許多情況下原始事務可能會回滾,Spring Batch 做出以下兩個保證

  • 適當的跳過方法(取決於錯誤發生的時間)每個項只調用一次。

  • SkipListener 始終在事務提交之前呼叫。這是為了確保監聽器呼叫的任何事務資源不會因 ItemWriter 中的失敗而回滾。

© . This site is unofficial and not affiliated with VMware.