获取 reader 中的 JobParameters 值

Get values of JobParameters in reader

我在获取 JobConfiguration Class 中的 JobParameter 值时遇到问题。 就像文档中的解释一样,我使用 :

@Value("#{jobParameters['xxxxxxxx']}") String xxxxxxx

@StepScope

但是,我有以下错误:

Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: 
Failed to instantiate [org.springframework.batch.core.Job]: Factory method 'PeopleJobConfiguration' threw exception; 
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.step1': 
Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; 
nested exception is java.lang.IllegalStateException: No context holder available for step scope

我的错误是在我的步骤之前使用了@StepScope。 这是我更正后的代码:

@SpringBootApplication
public class SpringBatchSimpleTestApplication {

    private static final Logger log = LoggerFactory.getLogger(SpringBatchSimpleTestApplication.class);

    public static void main(String[] args) throws Exception {

        Resource[] resource = ctx.getResources("file:c:/tmp/person*.csv");
        String filename;

        for (int i = 0; i < resource.length; i++) {
            filename = resource[i].getFile().getName();

            Job job = ctx.getBean("PersonJobConfiguration", Job.class);
            JobLauncher jobLauncher = ctx.getBean(JobLauncher.class);

            JobParameters params = new JobParametersBuilder()
                .addString("file123", filename)
                .toJobParameters();

            jobLauncher.run(job, params);
        }
    }
}

=========================================== ==================

@Configuration
@EnableBatchProcessing
public class PeopleJobConfiguration {
    
    private static final Logger log = LoggerFactory.getLogger(PeopleJobConfiguration.class);


    @Autowired
    public JobBuilderFactory jobBuilderFactory;

    @Autowired
    public StepBuilderFactory stepBuilderFactory;
    
    @StepScope
    @Bean
    public FlatFileItemReader<Person> reader1(@Value("#{jobParameters['file123']}") String file123) {
        
        log.debug("A-file123: "+file123);
        
        return new FlatFileItemReaderBuilder<Person>() 
                  .name("personItemReader")
                  .resource(new ClassPathResource(file123))
                  .lineTokenizer(new FixedLengthTokenizer()  {{ setNames("firstName", "lastName", "age'"); setColumns(new Range(1,4), new Range(5,6),new Range(7)); }})
                  .fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{ setTargetType(Person.class); }})
                  .build()
                  ;
    }
    

    @Bean
    public PersonItemProcessor processor() {
        return new PersonItemProcessor();
    }
    
    
    @Bean
    public JdbcBatchItemWriter<Person> writer1(DataSource dataSource) {
                  
    JdbcBatchItemWriter<Person> jdbcBatchItemWriter = new JdbcBatchItemWriter<>();
    jdbcBatchItemWriter.setAssertUpdates(true);
    jdbcBatchItemWriter.setDataSource(dataSource);
    jdbcBatchItemWriter.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)");
    jdbcBatchItemWriter.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>());

    return jdbcBatchItemWriter;
    }

    
    @Bean
    public JdbcBatchItemWriter<Person> writer2(DataSource dataSource) {
        return new JdbcBatchItemWriterBuilder<Person>()
            .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
            .sql("INSERT INTO people2 (first_name, last_name, age) VALUES (:firstName, :lastName, :age)")
            .dataSource(dataSource)
            .build();
    }
    
    
     @Bean
        public CompositeItemWriter compositeItemWriter(JdbcBatchItemWriter<Person> writer1,JdbcBatchItemWriter<Person> writer2) {
                        
                CompositeItemWriter itemWriter = new CompositeItemWriter();
                itemWriter.setDelegates(Arrays.asList(writer1, writer2));

                return itemWriter;
                }
    
    @Bean
    public Job PeopleJobConfiguration(JobEndListener listener, Step step1) {
        
        return jobBuilderFactory.get("PeopleJobConfiguration")
            .listener(listener)
            .flow(step1)
            .end()
            .build();
    }

    
    @Bean
    public Step step1(JdbcBatchItemWriter<Person> writer1,JdbcBatchItemWriter<Person> writer2, FlatFileItemReader<Person> reader1) {
        
        log.debug("B-file123: "+file123);
        
        return stepBuilderFactory.get("step1")
            .<Person,Person> chunk(3)
            .reader(reader1)
            .writer(compositeItemWriter(writer1, writer2))
            .build();
    }
    
}

在这里定义一个step-scoped Step bean是没有意义的:

@StepScope
@Bean
public Step step1(JdbcBatchItemWriter<Person> writer1,JdbcBatchItemWriter<Person> writer2, @Value("#{jobParameters['file123']}") String file123) {
    
    log.debug("B-file123: "+file123);
    
    return stepBuilderFactory.get("step1")
        .<Person,Person> chunk(3)
        .reader(reader1(file123))
        .writer(compositeItemWriter(writer1, writer2))
        .build();
}

您需要删除 @StepScope 并在步骤中注入 reader ,就像您为作家所做的那样:

@Bean
public Step step1(JdbcBatchItemWriter<Person> writer1,JdbcBatchItemWriter<Person> writer2, FlatFileItemReader<Person> reader) {
    
    log.debug("B-file123: "+file123);
    
    return stepBuilderFactory.get("step1")
        .<Person,Person> chunk(3)
        .reader(reader)
        .writer(compositeItemWriter(writer1, writer2))
        .build();
}