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

Spring Batch:将onSkipInRead异常信息存入batch_step_execution的EXIT_MESSAGE

Spring Batch:将读取跳过信息存入batch_step_execution并设置自定义EXIT_STATUS

嘿,作为Spring Batch新手,你的需求完全可行!Spring Batch提供了灵活的Listener扩展机制,刚好能帮你实现把跳过的记录信息存入batch_step_execution表的EXIT_MESSAGE字段,同时将EXIT_STATUS设置为SKIPPED的需求。咱们一步步来实现:

核心思路

要实现这个功能,我们需要:

  • 扩展自定义SkipListener,不仅记录日志,还要收集所有跳过的异常信息
  • 结合StepExecutionListener获取当前Step的执行上下文,用来更新EXIT_MESSAGE和EXIT_STATUS
  • 将自定义Listener注册到你的Step中,让Spring Batch在执行流程中调用它

修改后的自定义SkipListener代码

下面是调整后的IntroductionSkipListener,它同时实现了SkipListener和StepExecutionListener接口:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.core.annotation.BeforeStep;
import org.springframework.batch.core.listener.SkipListener;

public class IntroductionSkipListener implements SkipListener<Introduction, Introduction>, StepExecutionListener {

    private static final Logger LOG = LoggerFactory.getLogger(IntroductionSkipListener.class);
    private StepExecution stepExecution;
    private final StringBuilder skipMessages = new StringBuilder();

    @Override
    @BeforeStep
    public void beforeStep(StepExecution stepExecution) {
        // 保存当前Step的执行上下文
        this.stepExecution = stepExecution;
    }

    @Override
    public void onSkipInRead(Throwable t) {
        String skipDetail = String.format("Item was skipped in read due to: %s", t.getMessage());
        LOG.error(skipDetail);
        // 收集跳过信息
        skipMessages.append(skipDetail).append(System.lineSeparator());
    }

    @Override
    public void onSkipInWrite(Introduction item, Throwable t) {
        String skipDetail = String.format("Item %s was skipped in write due to : %s", item, t.getMessage());
        LOG.error(skipDetail);
        skipMessages.append(skipDetail).append(System.lineSeparator());
    }

    @Override
    public void onSkipInProcess(Introduction item, Throwable t) {
        String skipDetail = String.format("Item %s was skipped in process due to: %s", item, t.getMessage());
        LOG.error(skipDetail);
        skipMessages.append(skipDetail).append(System.lineSeparator());
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        // 如果有跳过记录,更新EXIT_MESSAGE和EXIT_STATUS
        if (skipMessages.length() > 0) {
            // 将收集的跳过信息写入batch_step_execution的EXIT_MESSAGE字段
            stepExecution.setExitMessage(skipMessages.toString());
            // 返回自定义的SKIPPED状态
            return new ExitStatus("SKIPPED", skipMessages.toString());
        }
        // 如果没有跳过,保持原有状态
        return stepExecution.getExitStatus();
    }
}

代码说明

  • 通过@BeforeStep注解获取当前Step的StepExecution实例,这是我们更新数据库表字段的关键入口
  • 用StringBuilder收集所有跳过的详细信息,避免频繁字符串拼接的性能问题
  • 在afterStep方法中,判断是否有跳过记录:如果有,就把收集的信息设置到stepExecution的exitMessage,同时返回自定义的ExitStatus("SKIPPED"),这个状态会自动同步到batch_step_execution表的EXIT_STATUS字段

注册Listener到你的Step

接下来需要把这个自定义Listener注册到你的Step配置中,同时要确保开启了容错机制(因为跳过功能依赖容错配置):

import org.springframework.batch.core.Step;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.transaction.PlatformTransactionManager;

@Bean
public Step introductionStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
    return new StepBuilder("introductionStep", jobRepository)
            .<Introduction, Introduction>chunk(10, transactionManager)
            .reader(yourIntroductionReader()) // 替换成你的ItemReader实现
            .processor(yourIntroductionProcessor()) // 替换成你的ItemProcessor实现
            .writer(yourIntroductionWriter()) // 替换成你的ItemWriter实现
            .faultTolerant() // 开启容错机制,必须配置才能使用跳过功能
            .skip(ParseException.class) // 指定要跳过的异常类型(比如你的解析异常)
            .skipLimit(10) // 设置允许跳过的最大数量,根据你的需求调整
            .listener(new IntroductionSkipListener()) // 注册自定义SkipListener
            .build();
}

关键配置说明

  • faultTolerant():必须开启这个配置,Spring Batch的跳过功能才会生效
  • skip(ParseException.class):这里要指定你希望跳过的异常类型,比如你例子中的解析错误对应的ParseException
  • skipLimit(10):设置允许跳过的最大记录数,超过这个数量后Step会直接失败

验证效果

当你的Step执行过程中出现读取跳过的情况时:

  1. batch_step_execution表的EXIT_MESSAGE字段会存储你收集的所有跳过详细信息(就像你提供的那段异常日志)
  2. EXIT_STATUS字段会被设置为SKIPPED

作为Spring Batch新手,这个实现方式非常直观,完全利用了框架原生的扩展点,不需要额外的复杂配置,刚好能满足你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:23:09