如何在春季批处理中从 ItemReader 访问作业参数?

2022-08-31 12:51:50

这是我的一部分:job.xml

<job id="foo" job-repository="job-repository">
  <step id="bar">
    <tasklet transaction-manager="transaction-manager">
      <chunk commit-interval="1"
        reader="foo-reader" writer="foo-writer"
      />
    </tasklet>
  </step>
</job>

这是项目读取器:

import org.springframework.batch.item.ItemReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("foo-reader")
public final class MyReader implements ItemReader<MyData> {
  @Override
  public MyData read() throws Exception {
    //...
  }
  @Value("#{jobParameters['fileName']}")
  public void setFileName(final String name) {
    //...
  }
}

这就是Spring Batch在运行时所说的话:

Field or property 'jobParameters' cannot be found on object of 
type 'org.springframework.beans.factory.config.BeanExpressionContext'

这是怎么回事?在 Spring 3.0 中,我在哪里可以阅读有关这些机制的更多信息?


答案 1

如前所述,您的读者需要“步进”范围。您可以通过注释完成此操作。如果您将该注释添加到读者中,它应该对您有用,如下所示:@Scope("step")

import org.springframework.batch.item.ItemReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("foo-reader")
@Scope("step")
public final class MyReader implements ItemReader<MyData> {
  @Override
  public MyData read() throws Exception {
    //...
  }

  @Value("#{jobParameters['fileName']}")
  public void setFileName(final String name) {
    //...
  }
}

默认情况下,此作用域不可用,但如果使用 XML 命名空间,则此作用域将不可用。如果不是,则根据 Spring 批处理文档,将以下内容添加到您的 Spring 配置中将使范围可用:batch

<bean class="org.springframework.batch.core.scope.StepScope" />

答案 2

如果要在单个 JavaConfig 类中定义 ItemReader 实例和 Step 实例。您可以使用@StepScope@Value批注,例如:

@Configuration
public class ContributionCardBatchConfiguration {

   private static final String WILL_BE_INJECTED = null;

   @Bean
   @StepScope
   public FlatFileItemReader<ContributionCard> contributionCardReader(@Value("#{jobParameters['fileName']}")String contributionCardCsvFileName){

     ....
   }

   @Bean
   Step ingestContributionCardStep(ItemReader<ContributionCard> reader){
         return stepBuilderFactory.get("ingestContributionCardStep")
                 .<ContributionCard, ContributionCard>chunk(1)
                 .reader(contributionCardReader(WILL_BE_INJECTED))
                 .writer(contributionCardWriter())
                 .build();
    }
}

诀窍是将 null 值传递给 itemReader,因为它将通过注释注入。@Value("#{jobParameters['fileName']}")

感谢 Tobias Flohre 的文章:Spring Batch 2.2 – JavaConfig Part 2:JobParameters、ExecutionContext 和 StepScope


推荐