java - Spring Batch - 在处理器和写入器之间传递数据

标签 java spring spring-boot spring-batch

我有一个 spring 批处理,其中包含读取器->处理器->写入器

黑白传递的数据类型为Emp :

class Emp {
    iny id;
    String name;
    EmpTypeEnum empType;    // HR, Dev, Tester, etc.

    // getters and setters
}

Reader 中的 CSV 文件读取简单的批量数据,里面的一些处理Processor & 并且输出 CSV 文件由 Writer 写入.

但是除了这个输出 CSV 文件之外,我想生成一个辅助输出文件,其中仅包含每个 EmpType 的计数。 ,即人力资源、开发和测试人员的总数。

我正在考虑在 processor 内执行计数只是,例如:

public class EmpItemProcessor implements ItemProcessor<Emp, Emp> {

    int countHr;
    int countDev;
    int countTester;


        @Override
        public Person process(final Emp emp) throws Exception {

        if (item.getEmpType.equals(EmpTypeEnum.HR) {
            countHr++;
        } else if // .....

        // other processor on emp

            return emp;
        }

}

但如你所见,我只能返回 Emp来自Processor ,那么我如何从处理器传递 countHr、countDev 等 并使用它来创建辅助文件?

请提出建议。如果您认为任何其他方法会更好,请提出建议。

谢谢

最佳答案

您可以使用 ItemWriteListenerJobExecutionListenerSupport 来实现此目的。

  1. 定义一个 ItemWriteListener ,每次调用 writer 后都会调用它。

  2. 在此监听器中,每次都会更新执行上下文中的计数器

  3. 编写一个JobExecutionListener,整个作业完成后将调用该监听器,您可以在其中从执行上下文中读取值并进行进一步处理。

    @Component
    @JobScope
    public class EmployeeWriteListener implements ItemWriteListener<Emp> {
    
      @Value("#{jobExecution.executionContext}")
      private ExecutionContext executionContext;
    
    
      @Override
      public void afterWrite(final List<? extends Emp> paramList) {
    
         final int counter =
              this.executionContext.getInt("TOTAL_EXPORTED_ITEMS", 0);
          this.executionContext.putInt("TOTAL_EXPORTED_ITEMS", counter + 1);
        }
    
      }
    }
    
    
    
    @Component
    @JobScope
    public class EmployeeNotificationListener extends JobExecutionListenerSupport  {
    
    @Override
    public void afterJob(final JobExecution jobExecution) {
    
      jobExecution.getExecutionContext()
          .getInt("TOTAL_EXPORTED_ITEMS")
      ...................
       }
     }
    

您应该在声明步骤和作业时注册这些监听器。

this.jobBuilders.get("someJob").incrementer(new RunIdIncrementer()).listener(new EmployeeNotificationListener())
        .flow(this.getSomeStep()).end().build();
//instead of new(..) you should Autowire listener

public Step getSomeStep() {

  return stepBuilders.get("someStep").<X, Y>chunk(10)
      .reader(this.yourReader).processor(this.yourProcessor)
      .writer(this.yourProcessor).listener(this.EmployeeWriteListener)
      .build();
}

关于java - Spring Batch - 在处理器和写入器之间传递数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48253260/

相关文章:

java - 如何将多个 Activity 锁定为纵向?

java - 如何覆盖 Spring bean 定义但仍然引用被覆盖的 bean?

java - Spring 项目 - 未指定类世界配置

java - Spring-boot:需要一个名为 'entityManagerFactory' 的 bean,但找不到

java - 我可以使用 HandshakeInterceptor 和 graphql-spring-boot-starter 来获取 Cookie 吗?

java - 项目gradle插件的加载类路径应用于

java - Android Studio 在按钮单击时更改 fragment

java - 如何排除/重定向 web.xml 或 Guice servlet 模块中的某些 url 模式?

java - Spring-MVC:调用 validator ,而不是从 Controller 内部

spring-boot - Thymeleaf 解析预处理字符串到日期并格式化它