Spring Batch 跳過策略配置

Spring Batch 跳過策略配置

Spring batch job執行過程中遇到任何錯誤,默認情況下將使得相應步驟執行失敗。但有些場景我們希望跳過造成特定異常的當前處理項。本文探討Spring batch 提供的兩種方法配置跳過邏輯。

1.示例環境說明

爲了簡化說明,本文重用Spring Batch 入門教程 中的示例,實現把csv文件中的一些財務數據轉換爲xml格式。

但我們增加一些錯誤數據:

username, user_id, transaction_date, transaction_amount
devendra, 1234, 31/10/2015, 10000
john, 2134, 3/12/2015, 12321
robin, 2134, 2/02/2015, 23411
, 2536, 3/10/2019, 100
mike, 9876, 5/11/2018, -500
, 3425, 10/10/2017, 9999

最後三行有一些無效數據,其中第5、7行沒有username字段,第6行金額值爲負數。下面章節我們的目標就是配置讓批處理程序跳過這些錯誤數據。

2. 跳過限制和該跳過異常的配置

2.1. 使用skip 和 skipLimit方法

下面先討論第一中方法,使用skip 和 skipLimit方法實現執行失敗時跳過處理項。

@Bean
public Step skippingStep(ItemProcessor<Transaction, Transaction> processor, ItemWriter<Transaction> writer) throws ParseException {
    return stepBuilderFactory
      .get("skippingStep")
      .<Transaction, Transaction>chunk(10)
      .reader(itemReader(invalidInputCsv))
      .processor(processor)
      .writer(writer)
      .faultTolerant()
      .skipLimit(2)
      .skip(MissingUsernameException.class)
      .skip(NegativeAmountException.class)
      .build();
}

首先需要啓用skip功能,需要在構建步驟時包括faultTolerant() 方法調用。在skip 和 skipLimit方法中,定義想跳過的異常類及最大跳過項數量。

上面示例中,如果在執行讀、處理或寫過程中無論遇到MissingUsernameException 或 NegativeAmountException 異常,當前正在處理的數據項被忽略並計數總數不超過2條。因此,第三次任何異常發生則整個執行失敗。

2.2. 使用noSkip方法

在前面示例中,任何其他類型異常(除了 MissingUsernameException 和 NegativeAmountException)仍會導致執行失敗。但有些場景指定異常發生執行步驟失敗而跳過任何其他異常更合適。

下面看如何使用skip, skipLimit, noSkip方法進行配置:

@Bean
public Step skippingStep( ItemProcessor<Transaction, Transaction> processor, ItemWriter<Transaction> writer) throws ParseException {
    return stepBuilderFactory
      .get("skippingStep")
      .<Transaction, Transaction>chunk(10)
      .reader(itemReader(invalidInputCsv))
      .processor(processor)
      .writer(writer)
      .faultTolerant()
      .skipLimit(2)
      .skip(Exception.class)
      .noSkip(SAXException.class)
      .build();
}

這裏配置讓 Spring Batch除了SAXException異常外跳過任何異常,則意味着SAXException 異常總會引發步驟執行失敗。配置中skip() 和 noSkip() 順序沒有影響。

3. 使用自定義跳過策略

實際應用中可能需要更復雜的跳過檢查機制,因此Spring Batch框架提供了SkipPolicy 接口。我們可以實現自己的跳過邏輯並插入至步驟定義中。

繼續使用前面的示例,假如我們仍需定義最大跳過項爲2,僅跳過MissingUsernameException 和 NegativeAmountException 兩種異常。但再增加一個約束條件,僅當金額不超過一定限制時才能跳過NegativeAmountException異常。自定義的SkipPolicy實現如下:

public class CustomSkipPolicy implements SkipPolicy {
 
    private static final int MAX_SKIP_COUNT = 2;
    private static final int INVALID_TX_AMOUNT_LIMIT = -1000;
 
    @Override
    public boolean shouldSkip(Throwable throwable, int skipCount) 
      throws SkipLimitExceededException {
 
        if (throwable instanceof MissingUsernameException && skipCount < MAX_SKIP_COUNT) {
            return true;
        }
 
        if (throwable instanceof NegativeAmountException && skipCount < MAX_SKIP_COUNT ) {
            NegativeAmountException ex = (NegativeAmountException) throwable;
            if(ex.getAmount() < INVALID_TX_AMOUNT_LIMIT) {
                return false;
            } else {
                return true;
            }
        }
 
        return false;
    }
}

現在我們能在定義步驟中使用自定義跳過策略:

@Bean
public Step skippingStep(
  ItemProcessor<Transaction, Transaction> processor,
  ItemWriter<Transaction> writer) throws ParseException {
    return stepBuilderFactory
      .get("skippingStep")
      .<Transaction, Transaction>chunk(10)
      .reader(itemReader(invalidInputCsv))
      .processor(processor)
      .writer(writer)
      .faultTolerant()
      .skipPolicy(new CustomSkipPolicy())
      .build();
}

與前面配置類似,仍需要使用faultTolerant() 方法啓用跳過功能。但這次沒調用skip() 或 noSkip(),而是使用skipPolicy()方法並指定自定義的SkipPolicy 接口實現。

我們看到這種方法更加靈活,爲實際應用中理想選擇。

4. 總結

本文我們提供兩種方法實現Spring Batch的容錯處理功能。雖然使用skipLimit() 及 skip() 、noSkip()方法比較簡單,但使用自定義的SkipPolicy實現更強大、靈活。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章