You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确处理Spring Batch Step Writer异常以跳过错误元素继续执行

问题1解答

你当前的代码逻辑里已经对三类异常做了显式捕获,且捕获后没有向上抛出异常,所以触发异常时只会跳过当前出错的单个元素,不会导致整个Job失败。但这种处理方式存在两个明显缺陷:

  • Spring Batch框架本身感知不到该条记录处理失败,你无法通过框架自带的跳过统计、失败记录监听等能力做后续的错误溯源、重跑处理
  • 仅打印异常栈的容错方式无法有效留存错误上下文,后续排查问题时无法定位具体是哪条记录、因为什么原因处理失败

问题2解答

你当前的写法本身不会导致Job失败,但更推荐使用Spring Batch原生的跳过机制实现容错,既能实现单条错误记录跳过的需求,又能利用框架的能力做错误管理,改造步骤如下:

  1. 首先修改你的NotaryWriter代码,去掉手动捕获异常的逻辑,直接把异常向上抛出:
@Component
public class NotaryWriter implements ItemWriter<NotaryDetails> {
    
    @Autowired
    private WpService wpService;

    public NotaryWriter(WpService wpService) {
        super();
        this.wpService = wpService;
    }

    @Override
    public void write(List<? extends NotaryDetails> items) throws Exception {
        items.stream().forEach(currentNotary -> {
            System.out.println("NotaryWriter - WRITING OUTPUT: " + currentNotary.toString());
            int newNotaryPostId = this.wpService.insertOrUpdateNotaryAsWpPost(currentNotary);   
        });
    }
}
  1. 在Step配置中添加跳过规则,指定需要跳过的异常类型、最大跳过次数,同时可以配置SkipListener来留存失败记录的上下文:
@Bean
public Step notaryProcessStep(StepBuilderFactory stepBuilderFactory, 
                              ItemReader<NotaryDetails> notaryReader,
                              NotaryWriter notaryWriter,
                              SkipListener<NotaryDetails, NotaryDetails> skipListener) {
    return stepBuilderFactory.get("notaryProcessStep")
            .<NotaryDetails, NotaryDetails>chunk(10) // 按你实际的chunk大小配置
            .reader(notaryReader)
            .writer(notaryWriter)
            // 配置跳过规则
            .skip(JsonProcessingException.class)
            .skip(UnsupportedEncodingException.class)
            .skip(URISyntaxException.class)
            // 配置最大跳过次数,超过后Job才会失败
            .skipLimit(100) 
            // 可选:配置跳过监听器,记录失败的记录信息
            .listener(skipListener)
            .build();
}
  1. (可选)自定义SkipListener实现,记录失败的记录详情到日志或者错误表中,方便后续排查:
@Component
public class NotarySkipListener implements SkipListener<NotaryDetails, NotaryDetails> {
    private static final Logger LOGGER = LoggerFactory.getLogger(NotarySkipListener.class);

    @Override
    public void onSkipInRead(Throwable t) {
        // 读阶段跳过的逻辑
    }

    @Override
    public void onSkipInWrite(NotaryDetails item, Throwable t) {
        LOGGER.error("处理公证人记录失败,记录内容:{},错误原因:{}", item.toString(), t.getMessage(), t);
        // 也可以写入错误表,后续做重跑
    }

    @Override
    public void onSkipInProcess(NotaryDetails item, Throwable t) {
        // 处理阶段跳过的逻辑
    }
}

这种原生实现的优势在于:

  • 框架自动完成错误记录的跳过,不需要你手动在业务代码里做异常捕获,代码更简洁
  • 可以通过Spring Batch的执行上下文直接查询跳过的记录数,不需要自己做统计
  • 可以统一管理所有错误记录的处理逻辑,避免散落在各个业务组件中

内容的提问来源于stack exchange,提问作者AndreaNobili

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 11:45:04