SpringBatch 监听器之Job监听器(JobExecutionListener)和Step监听器(StepExecutionListener)(五)

本文介绍了如何在SpringBatch中使用Job监听器JobExecutionListener和Step监听器StepExecutionListener。通过两种实现方式,包括注解和接口实现,详细讲解了它们在job和step执行前后进行数据处理的场景。此外,提供了相关监听器的使用示例,以帮助优化代码逻辑。

前言:例我们在执行job时候,可能需要在job执行之前预先对一些数据做处理,或者在job执行之后需要做一些处理。这时候我们就可以使用到监听器来帮做我们处理,SpringBatch已经帮我们预先留好接口了。

代码已上传GitHub上面地址:https://github.com/FadeHub/spring-boot-learn/tree/master/spring-boot-springbatch

在spring batch中主要以以下七种监听器为主:

  • Step监听器 :监听step的执行开始和结束;
  • Job监听器 :监听job的执行开始和结束;
  • SkipListener监听器 :在读、处理、写的过程中,监听跳过的异常;
  • ChunkListener监听器 :监听的chunk的执行开始和结束,或者监听chunk出错
  • ItemReadListener监听器:监听 读之前、读之后、读的时候发生错误
  • ItemProcessListener监听器:监听 处理之前、处理之后、处理的时候发生错误
  • ItemWriteListener监听器:监听 写之前、写之后、写的时候发生错误

SpringBatch其它文章直通车:

<think>我们正在讨论如何编写Spring Batch Writer监听器。根据引用[1][2]的内容,我们知道Spring Batch提供了多种监听器,包括Chunk监听器Skip监听器。但是,用户特别询问了Writer监听器的实现。实际上,Spring Batch并没有直接提供名为"Writer监听器"的接口,但我们可以通过以下方式实现对Writer操作的监听: ### 1. 使用`ItemWriteListener`接口 这是最直接的方式,它提供了三个方法: - `beforeWrite()`: 在Writer执行前调用 - `afterWrite()`: 在Writer成功执行后调用 - `onWriteError()`: 在Writer执行出错时调用 #### 实现示例: ```java import org.springframework.batch.core.ItemWriteListener; import java.util.List; @Component @StepScope public class CustomWriteListener implements ItemWriteListener<YourData> { @Override public void beforeWrite(List<? extends YourData> items) { System.out.println("准备写入 " + items.size() + " 条数据"); } @Override public void afterWrite(List<? extends YourData> items) { System.out.println("成功写入 " + items.size() + " 条数据"); } @Override public void onWriteError(Exception exception, List<? extends YourData> items) { System.err.println("写入失败: " + items.size() + " 条数据,错误信息:" + exception.getMessage()); } } ``` ### 2. 在Step中注册监听器 ```java @Bean public Step myStep(StepBuilderFactory steps, ItemReader<YourData> reader, ItemWriter<YourData> writer, CustomWriteListener writeListener) { return steps.get("myStep") .<YourData, YourData>chunk(100) .reader(reader) .writer(writer) .listener(writeListener) // 注册监听器 .build(); } ``` ### 3. 使用注解方式(更简洁) 如果不希望实现完整接口,可以使用Spring Batch提供的注解: ```java import org.springframework.batch.core.annotation.BeforeWrite; import org.springframework.batch.core.annotation.AfterWrite; import org.springframework.batch.core.annotation.OnWriteError; @Component @StepScope public class AnnotatedWriteListener { @BeforeWrite public void beforeWrite(List<? extends YourData> items) { System.out.println("[注解]准备写入: " + items); } @AfterWrite public void afterWrite(List<? extends YourData> items) { System.out.println("[注解]写入完成: " + items); } @OnWriteError public void onWriteError(Exception exception, List<? extends YourData> items) { System.err.println("[注解]写入错误: " + items + " - " + exception.getMessage()); } } ``` ### 关键点说明: 1. **作用范围**: - `@StepScope`确保每次Step执行都会创建新的监听器实例 - 可访问JobExecutionContext中的属性(通过`@Value("#{stepExecutionContext[...]}")`) 2. **应用场景**: - 日志记录:跟踪写入过程 - 错误处理:自定义写入失败处理逻辑 - 性能监控:记录写入耗时(在before/after中计算时间差) 3. **与Chunk监听器的区别**: - Chunk监听器(如引用[1])作用于整个chunk周期(读+处理+写) - ItemWriteListener仅针对写入操作 > **注意**:当同时使用多个监听器时,执行顺序为: > 1. `ChunkListener.beforeChunk()` > 2. `ItemReadListener.beforeRead()` > 3. 读取/处理 > 4. `ItemWriteListener.beforeWrite()` > 5. 写入操作 > 6. `ItemWriteListener.afterWrite()` > 7. `ChunkListener.afterChunk()` ### 实际应用:写入前后添加头尾 ```java @Override public void beforeWrite(List<? extends YourData> items) { if (isFirstWrite()) { // 自定义判断逻辑 writer.writeHeader(); // 调用写入器输出文件头 } } @Override public void afterWrite(List<? extends YourData> items) { if (isLastChunk()) { // 自定义判断逻辑 writer.writeFooter(); // 输出文件尾 } } ``` §§相关问题§§ 1. 如何在Spring Batch中监听读取(Reader)操作? 2. 如何实现Spring Batch的全局作业监听器(JobListener)? 3. ItemWriteListenerChunkListener的使用场景有什么区别? 4. 在监听器中如何访问Spring Batch的上下文信息? 5. 如何为同一个Step配置多个不同类型的监听器?</think>在 Spring Batch 中,可以通过实现 **`ItemWriteListener` 接口** 或使用 **`@BeforeWrite`、`@AfterWrite`、`@OnWriteError` 注解** 来创建 Writer 监听器。以下是具体实现方法: --- ### 方法一:实现 ItemWriteListener 接口(推荐) ```java import org.springframework.batch.core.ItemWriteListener; import org.springframework.stereotype.Component; import java.util.List; @Component @StepScope public class CustomWriteListener implements ItemWriteListener<YourDataType> { // Writer执行前触发 @Override public void beforeWrite(List<? extends YourDataType> items) { System.out.println("准备写入 " + items.size() + " 条数据"); // 可添加预处理逻辑 } // Writer成功执行后触发 @Override public void afterWrite(List<? extends YourDataType> items) { System.out.println("成功写入 " + items.size() + " 条数据"); // 可添加后处理逻辑(如日志记录) } // Writer执行出错时触发 @Override public void onWriteError(Exception exception, List<? extends YourDataType> items) { System.err.println("写入失败: " + items.size() + " 条数据,错误信息:" + exception.getMessage()); // 可添加错误处理逻辑 } } ``` --- ### 方法二:使用注解方式(更简洁) ```java import org.springframework.batch.core.annotation.*; import org.springframework.stereotype.Component; import java.util.List; @Component @StepScope public class AnnotatedWriteListener { @BeforeWrite public void beforeWrite(List<? extends YourDataType> items) { System.out.println("[注解]准备写入: " + items.size() + " 条数据"); } @AfterWrite public void afterWrite(List<? extends YourDataType> items) { System.out.println("[注解]成功写入: " + items.size() + " 条数据"); } @OnWriteError public void onWriteError(Exception exception, List<? extends YourDataType> items) { System.err.println("[注解]写入错误: " + items.size() + " 条数据"); } } ``` --- ### 在 Step 中注册监听器 ```java @Bean public Step myStep(StepBuilderFactory steps, ItemReader<YourDataType> reader, ItemWriter<YourDataType> writer, CustomWriteListener writeListener) { // 注入监听器 return steps.get("myStep") .<YourDataType, YourDataType>chunk(100) .reader(reader) .writer(writer) .listener(writeListener) // 注册监听器 .build(); } ``` --- ### 关键特性说明 1. **监听时机**: - `beforeWrite()`:Writer执行前触发(可访问待写入数据) - `afterWrite()`:Writer成功执行后触发(可访问已写入数据) - `onWriteError()`:Writer执行失败时触发(可访问异常问题数据)[^1] 2. **作用域控制**: - `@StepScope` 确保每次Step执行都创建新的监听器实例 - 可访问Job参数:`@Value("#{jobParameters['param']}")` 3. **典型应用场景**: ```java @AfterWrite public void logWriteMetrics(List<? extends YourDataType> items) { metricsService.recordWriteCount(items.size()); // 记录写入指标 } @OnWriteError public void handleWriteFailure(Exception ex, List<?> items) { errorReporter.reportFailedItems(items, ex); // 报告失败数据 } ``` 4. **与Chunk监听器的区别**: - `ItemWriteListener` 只监听Writer操作 - `ChunkListener` 监听整个chunk周期(读+处理+写)[^1][^2] > **最佳实践**:对于纯Writer操作监听,优先选择 `ItemWriteListener`;若需监控整个chunk生命周期(包含读/处理/写),则使用 `ChunkListener`[^1]。 --- ### 常见问题解决方案 **问题:如何获取写入的文件路径?** ```java @BeforeWrite public void beforeWrite(ChunkContext chunkContext) { StepContext stepContext = chunkContext.getStepContext(); String filePath = stepContext.getJobParameters().getString("outputPath"); System.out.println("写入文件: " + filePath); } ``` **问题:如何跳过特定数据的写入?** 在 `beforeWrite` 中过滤数据: ```java @Override public void beforeWrite(List<? extends YourDataType> items) { items.removeIf(item -> item.shouldSkip()); // 动态过滤数据 } ```
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

境里婆娑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值