【问题标题】:Accessing Job Parameters Spring Batch访问作业参数 Spring Batch
【发布时间】:2017-06-15 02:51:16
【问题描述】:

我一直在努力使用 Spring Batch 访问作业的作业参数。到目前为止,这是我的实现。

@Configuration
@EnableBatchProcessing
@PropertySource("classpath:batch.properties")
public class CSVBatchServiceImpl extends StepExecutionListenerSupport implements CSVBatchService {
    private static final Logger LOGGER = LoggerFactory.getLogger(CSVBatchServiceImpl.class);
    @Autowired
    public JobBuilderFactory jobBuilderFactory;
    @Autowired
    public StepBuilderFactory stepBuilderFactory;

    private QuestionReader questionReader = new QuestionReader();

    @Bean(name = "importQuestionsJob")
    public Job importQuestionsJob() {
        return jobBuilderFactory.get("importQuestionsJob")
                .incrementer(new RunIdIncrementer())
                .flow(step1())
                .end()
                .build();
    }

    @Bean
    public Step step1() {
        return stepBuilderFactory.get("step1")
                .<Question, Question>chunk(2)
                .reader(questionReader.reader())
                .processor(processor())
                .build();
    }

    @Bean
    public QuestionProcessor processor() {
        return new QuestionProcessor();
    }
}

class QuestionReader extends StepExecutionListenerSupport {
    private static final Logger LOGGER = LoggerFactory.getLogger(QuestionReader.class);

    //TODO: remove this
    private static JsonNode getJsonNode(String str) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.readTree(str);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Bean
    public FlatFileItemReader<Question> reader() {
        FlatFileItemReader<Question> reader = new FlatFileItemReader<>();
        //TODO get this as a parameter
        reader.setResource(new ClassPathResource("duplicateLabels.csv"));
        reader.setLinesToSkip(1);
        reader.setLineMapper(new DefaultLineMapper<Question>() {{
            setLineTokenizer((new DelimitedLineTokenizer() {{
                setNames(new String[]{"label", "body", "real_answer"});
            }}));
            setFieldSetMapper(new QuestionFieldSetMapper());
        }});
        return reader;
    }

    private static class QuestionFieldSetMapper implements FieldSetMapper<Question> {
        public Question mapFieldSet(FieldSet fieldSet) {
            Question question = new Question();
            question.setLabel(fieldSet.readString(0));
            question.setBody(getJsonNode(fieldSet.readString(1)));
            question.setRealAnswer(getJsonNode(fieldSet.readString(2)));
            return question;
        }
    }
}

我这样称呼这份工作:

JobParameters parameters = new JobParametersBuilder()
        .addLong("time", System.currentTimeMillis())
        .addString("filePath", "file.csv")
        .toJobParameters();
jobLauncher.run(importQuestionsJob, parameters);

如何访问 reader 函数中的 filePath 参数?

【问题讨论】:

    标签: java spring spring-boot java-8 spring-batch


    【解决方案1】:

    另一个非常适用于ItemProcessorsItemReadersItemWriters 等的解决方案是@BeforeStep 注释。它由StepExecutionListener 支持,就像Eugene To mentioned 一样。这是该解决方案的一种捷径。

    实现可能如下所示

    @BeforeStep
    public void beforeStep(StepExecution stepExecution) {
        JobParameters jobParameters = stepExecution.getJobParameters();
    
        Long millis = jobParameters.getLong("time");
        String path = jobParameters.getString("filePath");
    }
    

    【讨论】:

      【解决方案2】:

      你应该可以的,

      @Value("#{jobParameters['filePath']}") String filePath;
      

      如果有任何问题,您可以尝试将您的读者置于@StepScope

      【讨论】:

      • 设置范围是强制性的,如果没有它,它将不起作用。
      • 如果你能告诉我我可以在哪里添加代码,我将不胜感激。
      • 我猜,您需要在 reader() 方法中使用它,以便您可以更改阅读器签名,如 reader(@Value("#{jobParameters['filePath']}") String filePath) 但请确保您使用 @StepScope 注释 reader 。在您的步骤定义中,您可以为此参数传递null,例如questionReader.reader(null)
      【解决方案3】:

      您可以将org.springframework.batch.core.listener.JobParameterExecutionContextCopyListener 添加到您的步骤中。

      TaskletStep step = stepBuilderFactory.get("my-best-step") .<Item, Item>chunk(10) .reader(myBestReader) .writer(myBestWriter) .listener(new JobParameterExecutionContextCopyListener()) .build();

      Listener 会将 JobParameters 复制到 ItemReader 的 open 和 update 方法中可用的 ExecutionContext

      【讨论】:

        【解决方案4】:

        访问作业参数的一种方法是在您的阅读器类中实现 StepExecutionListener,以利用其重写的方法 beforeStep 和 afterStep,

        @Override
        public void beforeStep(StepExecution stepExecution) {
           String filePath = (String) stepExecution.getJobExecution().getExecutionContext()
                .get("filePath");
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-02-09
          • 2018-08-31
          • 2017-11-09
          • 2016-11-09
          相关资源
          最近更新 更多