如何从其余服务开始批处理。afterJob运行,但是EnableBatchProcessing仅在部署后运行

Jim*_*m C 1 spring spring-mvc spring-batch spring-boot

我遵循了https://spring.io/guides/gs/batch-processing/教程,该教程基本上是读取电子表格,并在应用程序启动后将数据插入数据库中。我想在每次启动休息服务时执行读取过程,因此我在此应用程序中添加了一个控制器。打电话给我,我遵循了如何使用Rest Web Service触发工作中的建议现在出现了我的问题:每当我调用rest服务时,它仅运行afterJob方法。我阅读了如何根据应用程序参数选择要运行的spring批处理作业-Spring Boot Java Config(与我的问题有一定的相似之处)和其中指出的出色博客文章,但我仍然受困。我想在其余服务之后调用“ public ItemReader reader()”,我希望遵循与通过main()启动应用程序时执行的流程相同的流程。我的意思是,与springboot部署时的流程相同。我想我的困惑在于@EnableBatchProcessing或JobExecutionListenerSupport,但我真的很坚持。以下是最重要的代码段。

控制者

@Autowired
JobLauncher jobLauncher;

@Autowired
Job job;

@RequestMapping("/runit")
public void handle() throws Exception{
       JobParameters jobParameters =
                       new JobParametersBuilder()
                       .addLong("time",System.currentTimeMillis()).toJobParameters();
        jobLauncher.run(job, jobParameters);
}
Run Code Online (Sandbox Code Playgroud)

听众

@Component
public class JobCompletionNotificationListener extends   
    JobExecutionListenerSupport {

    @Override
    public void afterJob(JobExecution jobExecution) {
        if(jobExecution.getStatus() == BatchStatus.COMPLETED) {
Run Code Online (Sandbox Code Playgroud)

批量配置

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
    // tag::readerwriterprocessor[]
    @Bean
    public ItemReader<Person> reader() {
        FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>();
        reader.setResource(new ClassPathResource("sample-data.csv"));
        reader.setLineMapper(new DefaultLineMapper<Person>() {{
            setLineTokenizer(new DelimitedLineTokenizer() {{
                setNames(new String[] { "firstName", "lastName" });
            }});

            setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
                setTargetType(Person.class);
            }});
        }});

        return reader;
    }

    @Bean
    public ItemProcessor<Person, Person> processor() {
        return new PersonItemProcessor();
    }

    @Bean
    public ItemWriter<Person> writer(DataSource dataSource) {
        JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<Person>();
        writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>());

        writer.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)");

        writer.setDataSource(dataSource);
        return writer;
    }

    @Bean
    public Job importUserJob(JobBuilderFactory jobs, Step s1, JobExecutionListener listener) {
        return jobs.get("importUserJob")
                .incrementer(new RunIdIncrementer())
                .listener(listener)
                .flow(s1)
                .end()
                .build();
    }

    @Bean
    public Step step1(StepBuilderFactory stepBuilderFactory, ItemReader<Person> reader,
            ItemWriter<Person> writer, ItemProcessor<Person, Person> processor) {
        return stepBuilderFactory.get("step1")
                .<Person, Person> chunk(10)
                .reader(reader)
                .processor(processor)
                .writer(writer)
                .build();
    }
Run Code Online (Sandbox Code Playgroud)

application.properties

application.properties
# SPRING BATCH (BatchDatabaseInitializer)
spring.batch.job.enabled=false
spring.batch.initializer.enabled=false
Run Code Online (Sandbox Code Playgroud)

Mic*_*lla 5

在深入探讨此问题的聊天之后,真正的“问题”是ItemReader一次创建,而不是每个REST调用创建一次(也就是每次作业执行一次)。要解决此问题,请确定ItemReader步骤的范围。这样,您可以在每次运行时获得读取器的新实例,这还使您能够基于作业参数注入文件名。

从代码角度,更改此:

@Bean
public ItemReader<Person> reader() {
Run Code Online (Sandbox Code Playgroud)

对此:

@Bean
@StepScope
public FlatFileItemReader<Person> reader() {
Run Code Online (Sandbox Code Playgroud)

返回类型更改的原因是Spring Batch将自动ItemStream为您注册。但是,在使用时,@StepScope我们只会看到您定义的收益。在这种情况下,请ItemReader不要扩展/实现,ItemStream因此我们不知道您要返回的内容应该是自动注册的。通过返回,FlatFileItemReader我们可以看到所有接口/等,并可以为您应用“魔术”。