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实现更强大、灵活。

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