一篇文章教你学会使用SpringBatch 监听器Listener

文章目录

      • 一、SpringBatch监听器
      • 二、搭建SpringBatch开发环境
      • 三、监听器详细介绍
        • 1、JobExecutionListener
        • 2、StepExecutionListener
        • 3、ChunkListener
        • 4、ItemReaderListener
        • 5、ItemProcessListener
        • 6、ItemWriteListener
        • 7、SkipListener
      • 四、创建job执行监听器

写在前面: 我是「境里婆娑」。我还是从前那个少年,没有一丝丝改变,时间只不过是考验,种在心中信念丝毫未减,眼前这个少年,还是最初那张脸,面前再多艰险不退却。
写博客的目的就是分享给大家一起学习交流,如果您对 Java感兴趣,可以关注我,我们一起学习。

前言:为什么要写这篇文章,因为我们在用SpringBatch做批量时候,经常会在job执行之前之后,或者step之前之后做一些特殊处理,或者程序报错我们要把报错的数据抓出来。这时候SpringBatch提供的监听器可以很好的帮助我们解决这些问题。下面就让我们一步一步去研究SpringBatch监听器吧。

一、SpringBatch监听器

Spring Batch提供了多种监听器Listener,用于在任务处理过程中触发我们的逻辑代码。常用的监听器根据粒度从粗到细分别有:Job级别的监听器JobExecutionListener、Step级别的监听器StepExecutionListener、Chunk监听器ChunkListener、ItemReader监听器ItemReadListener、ItemWriter监听器ItemWriteListener和ItemProcessor监听器ItemProcessListener和SkipListener等。具体可以参考下表:

监听器 具体说明
JobExecutionListener 在Job开始之前(beforeJob)和之后(aflerJob)触发
StepExecutionListener 在Step开始之前(beforeStep)和之后(afterStep)触发
ChunkListener 在 Chunk 开始之前(beforeChunk),之后(afterChunk)和错误后(afterChunkError)触发
ItemReadListener 在 Read 开始之前(beforeRead>,之后(afterRead)和错误后(onReadError)触发
ItemProcessListener 在 Processor 开始之前(beforeProcess),之后(afterProcess)和错误后(onProcessError)触发
ItemWriteListener 在 Writer 开始之前(beforeWrite),之后(afterWrite)和错误后(onWriteError)触发
SkipListener 在 Skip(reder)时候,在 Skip(writer)时候,在 Skip(processor)时候

二、搭建SpringBatch开发环境

新建一个Spring Boot项目,版本为2.3.1.RELEASE,引入SpringBatch jar包,项目结构如下图所示:
如果对怎么快速搭建SpringBoot功能有疑问,请看此篇文章:

一篇文章教你学会使用SpringBoot实现文件上传和下载
一篇文章教你学会使用SpringBatch 监听器Listener_第1张图片

三、监听器详细介绍

每种监听器都可以通过两种方式使用:

  • 接口实现;
  • 注解驱动。

1、JobExecutionListener

Job监听器提供了两个方法,一个是beforeJob(),另一个是afterJob()。这个监听器我们可以做些参数的加载。比如在job执行之前把参数加载进去。在执行之后把参数清除等操作。

@Component
public class MyJobExecutionListener implements JobExecutionListener {
    @Override
    public void beforeJob(JobExecution jobExecution) {
        System.out.println("job执行之前做处理...");
    }

    @Override
    public void afterJob(JobExecution jobExecution) {
        System.out.println("job执行之后做处理...");
    }
}

2、StepExecutionListener

step监听器和job监听器功能差不多,也有两个方法beforeStep()和afterStep()。
afterStep()这个方法有返回值,可以设置step的执行状态。

@Component
public class MyStepExecutionListener implements StepExecutionListener {
    @Override
    public void beforeStep(StepExecution stepExecution) {
        System.out.println("step执行之前...");
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        System.out.println("step执行之后...");
        return null;
    }
}

3、ChunkListener

ChunkListener有三个方法beforeChunk()、afterChunk()、afterChunkError()。都能把chunk的上下文打印出来。通过beforeChunk和afterChunk可以把一个chunk的执行时间算出来。

@Component
public class MyChunkListener implements ChunkListener {
    @Override
    public void beforeChunk(ChunkContext chunkContext) {
        System.out.println("chunk执行之前:" +System.currentTimeMillis());
    }

    @Override
    public void afterChunk(ChunkContext chunkContext) {
        System.out.println("chunk执行之后:" +System.currentTimeMillis());
    }

    @Override
    public void afterChunkError(ChunkContext chunkContext) {
        System.out.println("chunk执行出错...");
    }
}

4、ItemReaderListener

reder监听器也有三个方法beforeRead、afterRead、onReadError
如果我们读到一条数据,需要处理,可以在afterReader之后做操作。

@Component
public class MyItemReadListener implements ItemReadListener {
    @Override
    public void beforeRead() {
        System.out.println("reder之前...");
    }

    @Override
    public void afterRead(Object o) {
        System.out.println("reder之后...");
    }

    @Override
    public void onReadError(Exception e) {
        System.out.println("reder报错...");
    }
}

5、ItemProcessListener

Process监听器也有三个方法,其实我们经常用的是onProcessError这个方法,这个方法可以在处理process时候把异常数据打印出来。可以快速定位问题。

@Component
public class MyItemProcessListener implements ItemProcessListener {
    @Override
    public void beforeProcess(Object o) {
        System.out.println("Process之前...");
    }

    @Override
    public void afterProcess(Object o, Object o2) {
        System.out.println("Process之h后...");
    }

    @Override
    public void onProcessError(Object o, Exception e) {
        System.out.println("Process报错...");
    }
}

6、ItemWriteListener

特别注意的是onWriteError这个方法,是吧这个list所有对象全部打印出来。

@Component
public class MyItemWriterListener implements ItemWriteListener {
    @Override
    public void beforeWrite(List list) {
        System.out.println("writer之前...");
    }

    @Override
    public void afterWrite(List list) {
        System.out.println("writer之后...");
    }

    @Override
    public void onWriteError(Exception e, List list) {
        System.out.println("writer异常...");
    }
}

7、SkipListener

skip监听器可以处理RPW报异常的时候把这些数据跳过。

@Component
public class MySkipListener implements SkipListener{
    @Override
    public void onSkipInRead(Throwable throwable) {
        System.out.println("skip reader...");
    }

    @Override
    public void onSkipInWrite(Object o, Throwable throwable) {
        System.out.println("skip write...");
    }

    @Override
    public void onSkipInProcess(Object o, Throwable throwable) {
        System.out.println("skip process...");
    }
}

四、创建job执行监听器

准备好这些监听器后,新建job包,然后在该包下新建ListenJobConfiguration:

/**
 * @author shuliangzhao
 * @Title: ListenJobConfiguration
 * @date 2020/7/12 14:55
 */
@Configuration
@EnableBatchProcessing
public class ListenJobConfiguration {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    private MyJobExecutionListener myJobExecutionListener;

    @Autowired
    private MyStepExecutionListener myStepExecutionListener;

    @Autowired
    private MyChunkListener myChunkListener;

    @Autowired
    private MyItemReadListener myItemReadListener;

    @Autowired
    private MyItemProcessListener myItemProcessListener;

    @Autowired
    private MyItemWriterListener myItemWriterListener;

    @Autowired
    private MySkipListener mySkipListener;

    @Bean
    public Job listenerJob() {
        return jobBuilderFactory.get("listenerJob")
                .listener(myJobExecutionListener)
                .start(listenerStep())
                .build();
    }

    @Bean
    public Step listenerStep() {
        return stepBuilderFactory.get("listenerStep")
                .listener(myStepExecutionListener)
                .listener(myChunkListener)
                .chunk(10)
                .reader(reader())
                .listener(myItemReadListener)
                .processor(processor())
                .listener(myItemProcessListener)
                .writer(list -> list.forEach(System.out::println))
                .listener(myItemWriterListener)
                .listener(mySkipListener)
                .build();

    }

    @Bean
    @StepScope
    public ItemReader<String> reader() {
        List<String> data = Arrays.asList("java", "c++", "javascript", "python");
        return new MyItemReader(data);
    }

    @Bean
    @StepScope
    public ItemProcessor<String, String> processor() {
        return item -> item + " language";
    }
}

public class MyItemReader implements ItemReader<String> {
    private Iterator<String> iterator;

    public MyItemReader(List<String> data) {
        this.iterator = data.iterator();
    }

    @Override
    public String read() {
        return iterator.hasNext() ? iterator.next() : null;
    }
}

上面代码我们在相应的位置配置了监听器(配置chunk监听器的时候,必须配置faultTolerant())。
启动项目,控制台日志打印如下:

job执行之前做处理...
2020-07-12 15:15:09.979  INFO 19104 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [listenerStep]
step执行之前...
chunk执行之前:1594538110015
reder之前...
reder之后...
reder之前...
reder之后...
reder之前...
reder之后...
reder之前...
reder之后...
reder之前...
Process之前...
Process之h后...
Process之前...
Process之h后...
Process之前...
Process之h后...
Process之前...
Process之h后...
writer之前...
java language
c++ language
javascript language
python language
writer之后...
chunk执行之后:1594538110057
step执行之后...
2020-07-12 15:15:10.068  INFO 19104 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [listenerStep] executed in 88ms
job执行之后做处理...

到此SpringBatch常用监听器已经全部介绍完毕。如果还有不明白的可以留言。

本文来源代码: SpringBatch监听器源码
—————————————————————————————————
由于本人水平有限,难免有不足,恳请各位大佬不吝赐教!

你可能感兴趣的:(springbatch,java)