如何从Spring Batch中的ItemReader访问作业参数?

yeg*_*256 67 java spring spring-batch

这是我的一部分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>
Run Code Online (Sandbox Code Playgroud)

这是项目读者:

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) {
    //...
  }
}
Run Code Online (Sandbox Code Playgroud)

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

Field or property 'jobParameters' cannot be found on object of 
type 'org.springframework.beans.factory.config.BeanExpressionContext'
Run Code Online (Sandbox Code Playgroud)

这有什么不对?在哪里可以阅读Spring 3.0中有关这些机制的更多信息?

Sea*_*ung 69

如上所述,您的读者需要"跨步"范围.您可以通过@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) {
    //...
  }
}
Run Code Online (Sandbox Code Playgroud)

默认情况下,此范围不可用,但如果您使用的是batchXML命名空间,则可以使用此范围.如果不是这样,根据Spring Batch文档,将以下内容添加到Spring配置中将使范围可用:

<bean class="org.springframework.batch.core.scope.StepScope" />
Run Code Online (Sandbox Code Playgroud)

  • `StepScope`现在默认可用 (6认同)

Ort*_*kni 21

如果要在单个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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

感谢Tobias Flohre的文章:Spring Batch 2.2 - JavaConfig第2部分:JobParameters,ExecutionContext和StepScope


aba*_*ogh 13

为了能够使用jobParameters,我认为您需要将读者定义为范围"步骤",但我不确定您是否可以使用注释来完成.

使用xml-config它会像这样:

<bean id="foo-readers" scope="step"
  class="...MyReader">
  <property name="fileName" value="#{jobExecutionContext['fileName']}" />
</bean>
Run Code Online (Sandbox Code Playgroud)

请参阅Spring Batch文档.

也许它可以通过@Scope在xml-config中使用和定义步骤范围来实现:

<bean class="org.springframework.batch.core.scope.StepScope" />
Run Code Online (Sandbox Code Playgroud)


Ale*_*uss 12

很晚,但你也可以通过注释@BeforeStep方法来做到这一点:

@BeforeStep
    public void beforeStep(final StepExecution stepExecution) {
        JobParameters parameters = stepExecution.getJobExecution().getJobParameters();
        //use your parameters
}
Run Code Online (Sandbox Code Playgroud)

  • 这仅在作业参数的使用*不改变ItemReader的状态*时才有用.如果它们例如用于指定要读取的数据,则读取器的并发执行可能导致不正确的行为. (8认同)

dmo*_*tta 5

再补充一个示例,您可以访问 JavaConfig 类中的所有作业参数:

@Bean
@StepScope
public ItemStreamReader<GenericMessage> reader(@Value("#{jobParameters}") Map<String,Object> jobParameters){
          ....
}
Run Code Online (Sandbox Code Playgroud)