[Spring 批处理][Mongo] 无法在 ItemReader read() 中读取 jobParameters

[Spring Batch][Mongo] Cannot read jobParameters in ItemReader read()

我已经设置了一个步骤配置和 ItemReader 以从 mongoDB 同一个文件 中读取数据,就像这样...

@Bean("STEP_FETCH_DATA")
public Step fetchDatabaseStep(
        ItemReader<ExampleDao> dataReader,
        DataProcessor dataProcessor,
        DataWriter dataWriter,
        @Qualifier("TASK_EXECUTOR") TaskExecutor taskExecutor
) {
    log.info("Initialize step: {}", "STEP_FETCH_DATA");
    return stepBuilderFactory.get("STEP_FETCH_DATA")
            .<ExampleDao, ExampleDao>chunk(chunkSize)
            .processor(dataProcessor)
            .reader(dataReader)
            .writer(dataWriter)
            .taskExecutor(taskExecutor)
            .build();
}

@Bean("dataReader")
@StepScope
public ItemReader<ExampleDao> read(@Value("#{jobParameters.get(\"batchRunDate\")}") String batchRunDate) throws UnexpectedInputException, ParseException, NonTransientResourceException {
    log.info("Reading start... batchRunDate : {}", batchRunDate);
    MongoItemReader<ExampleDao> reader = new MongoItemReader<>();
    reader.setTemplate(mongoTemplate);
    reader.setSort(new HashMap<String, Sort.Direction>() {{
        put("_id", Sort.Direction.DESC);
    }});
    reader.setTargetType(ExampleDao.class);
    reader.setQuery("{}");
    return reader;
}

从上面的代码,它可以访问我的 jobParameter 并按预期工作

但是,如果我像这样创建一个 class 来包含我的 mongo ItemReader

@Component
@Slf4j
public class DataReaderExample {

@Autowired
private MongoTemplate mongoTemplate;

@Bean
@StepScope
public ItemReader<ExampleDao> read(@Value("#{jobParameters.get(\"batchRunDate\")}") String 
batchRunDate) throws UnexpectedInputException, ParseException, NonTransientResourceException {
    log.info("Reading start... batchRunDate : {}", batchRunDate);
    MongoItemReader<ExampleDao> reader = new MongoItemReader<>();
    reader.setTemplate(mongoTemplate);
    reader.setSort(new HashMap<String, Sort.Direction>() {{
        put("_id", Sort.Direction.DESC);
    }});
    reader.setTargetType(ExampleDao.class);
    reader.setQuery("{}");
    return reader;
  }
}

然后像这样设置一个步骤配置。 (注意 .reader(dataReadExample.read(null))。我期望 @Value("#{[= read() 参数中的 40=]("batchRunDate") 将覆盖 null 值)

@Bean("STEP_FETCH_DATA")
public Step fetchDatabaseStep(
    DataReaderExample dataReadExample ,
    DataProcessor dataProcessor,
    DataWriter dataWriter,
    @Qualifier("TASK_EXECUTOR") TaskExecutor taskExecutor
) {
log.info("Initialize step: {}", "STEP_FETCH_DATA");
return stepBuilderFactory.get("STEP_FETCH_DATA")
        .<ExampleDao, ExampleDao>chunk(chunkSize)
        .processor(dataProcessor)
        .reader(dataReadExample.read(null))
        .writer(dataWriter)
        .taskExecutor(taskExecutor)
        .build();
}

My log.info("Reading start... batchRunDate : {}", batchRunDate); 批处理将始终打印为空值和@Value ("#{jobParameters.get("batchRunDate") 不工作。好像我无法访问 jobParameters。

谁能向我解释一下这种行为以及如何将 ItemReader 移动到另一个 class。我的目标是将 ItemReader 分离成另一个 class。谢谢!

您的 DataReaderExample 被声明为 @Component,它应该是 @Configuration class,您在其中声明了 bean 定义。

我建议将 read 方法更改为 itemReader 或类似的东西,因为它的目的是定义项目 reader bean 而不是实际读取数据。

完成后,您可以在应用程序上下文中导入 DataReaderExample 配置 class 并在您的步骤中自动装配项目 reader:

@Bean("STEP_FETCH_DATA")
public Step fetchDatabaseStep(
    ItemReader<ExampleDao> itemReader ,
    DataProcessor dataProcessor,
    DataWriter dataWriter,
    @Qualifier("TASK_EXECUTOR") TaskExecutor taskExecutor
) {
log.info("Initialize step: {}", "STEP_FETCH_DATA");
return stepBuilderFactory.get("STEP_FETCH_DATA")
        .<ExampleDao, ExampleDao>chunk(chunkSize)
        .processor(dataProcessor)
        .reader(itemReader)
        .writer(dataWriter)
        .taskExecutor(taskExecutor)
        .build();
}