Java-如何在SpringBatch应用程序中设置ExitCode

时间:2018-07-20 08:27:35

标签: java spring spring-boot spring-batch

我正在制作一个具有批处理和处理器的Spring Batch应用程序。 在处理器中,我引发了异常,而我的需要是根据我引发的异常将System.exit()应用程序。

但是我不知道该怎么做。

感谢您的答复

2 个答案:

答案 0 :(得分:0)

您可以在此article中找到很好的解释。一种实现方法是提供ExitCodeExceptionMapper bean,以将异常映射到某些特定的退出代码:

@Bean
ExitCodeExceptionMapper exceptionMapper() {
    return exception -> {
        if (exception.getCause() instanceof NumberFormatException) {
            return 80;
        }
        return 1;
    };
}

更新

这个小例子应该很清楚:

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
  @Bean
  ExitCodeExceptionMapper exitCodeExceptionMapper() {
    return exception -> {
      if (exception.getCause() instanceof MyException) {
        return 10;
      }
      return 1;
    };
  }

  public static void main(String[] args) {
    System.exit(SpringApplication
        .exit(SpringApplication.run(DemoApplication.class, args)));
  }

  @Override
  public void run(String... args) throws Exception {
    throw new MyException();
  }

  private class MyException extends RuntimeException {}
}

然后我执行以下命令来运行该应用程序:

mvn package
java -jar target/demo-1.0.0-SNAPSHOT.jar

执行此命令后,我可以使用以下Windows命令检查退出代码:

echo Exit Code is %errorlevel%

它返回:

Exit Code is 10

答案 1 :(得分:0)

  

我需要根据我抛出的异常对System.exit()应用程序

我不建议调用System.exit来杀死您的应用程序,因为这会导致您在不正常关闭进程和清理资源的情况下终止您的工作。

如果使用CommandLineJobRunner,则可以提供自定义ExitCodeMapper。看到这里:https://docs.spring.io/spring-batch/4.0.x/reference/html/job.html#exitCodes

如果使用Spring Boot,则需要使用返回值System.exit来调用SpringApplication。您可以在这里找到一个示例:https://github.com/spring-projects/spring-boot/blob/master/spring-boot-samples/spring-boot-sample-batch/src/main/java/sample/batch/SampleBatchApplication.java#L67,并在以下参考文档中找到更多详细信息:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-application-exit

现在要能够自定义处理器中发生异常时作业的退出代码,您需要:

  • 在作业级别传播此信息。通过访问处理器中的作业执行上下文,然后在作业侦听器中使用它,可以实现这一点
  • 使用自定义ExitCodeGenerator通过Spring Boot发送的JobExectutionEvent来访问作业执行并自定义退出代码

这里是一个例子:

@Configuration
@EnableBatchProcessing
public class MyJob {

@Autowired
private JobBuilderFactory jobs;

@Autowired
private StepBuilderFactory steps;

@Bean
public Step step() {
    return steps.get("step")
            .<Integer, Integer>chunk(2)
            .reader(new ListItemReader<>(Arrays.asList(1, 2, 3, 4)))
            .processor(new ItemProcessor<Integer, Integer>() {

                private StepExecution stepExecution;

                @BeforeStep
                public void beforeStep(StepExecution stepExecution) {
                    this.stepExecution = stepExecution;
                }

                @Override
                public Integer process(Integer item) {
                    if (item.equals(3)) {
                        stepExecution.getJobExecution().getExecutionContext().put("failure", "item not accepted");
                        throw new IllegalArgumentException("3 is not accepted");
                    }
                    return item;
                }
            })
            .writer(items -> {
                for (Integer item : items) {
                    System.out.println("item = " + item);
                }
            })
            .build();
}

@Bean
public Job job() {
    return jobs.get("job")
            .start(step())
            .listener(new JobExecutionListenerSupport() {
                @Override
                public void afterJob(JobExecution jobExecution) {
                    String failure = jobExecution.getExecutionContext().getString("failure");
                    if (failure != null && failure.equalsIgnoreCase("item not accepted")) {
                        jobExecution.setExitStatus(new ExitStatus("Not Accepted"));
                    }
                }
            })
            .build();
}

@Bean
public ExitCodeGenerator exitCodeGenerator () {
    return new MyExitCodeGenerator();
}

static class MyExitCodeGenerator implements ExitCodeGenerator, ApplicationListener<JobExecutionEvent> {

    private JobExecution jobExecution;

    @Override
    public int getExitCode() {
        if (jobExecution.getExitStatus().getExitCode().equalsIgnoreCase("Not Accepted")) {
            return 42;
        }
        return 0;
    }

    @Override
    public void onApplicationEvent(JobExecutionEvent jobExecutionEvent) {
        this.jobExecution = jobExecutionEvent.getJobExecution();
    }
   }

}

如果您使用以下命令运行此

@SpringBootApplication
public class DemoExitCodeApplication {

public static void main(String[] args) {
    System.exit(
            SpringApplication.exit(
                SpringApplication.run(DemoExitCodeApplication.class, args)
            )
    );
   }
}

JVM的退出代码是42,这是在处理器中引发异常时设置的值。