通过 Spring 批量作业步骤维护作业前对象

Maintain pre-job object through Spring Batch job steps

对于我的批处理应用程序,在执行 Spring 批处理作业之前,我需要执行一些步骤。例如,我需要执行特定查询并将数据存储在 属性 - 具有复杂类型的列表 (List<ComplexType>) - 以便它可以在整个 Spring 中使用和操作批处理作业(主要在 ItemReader 中)。

我试过在我的列表中自动装配并在步骤中访问它,但我无法那样访问列表中的数据。我在我的列表中得到一个空的 ComplexType,无论在工作之前我的自动装配列表 属性 添加了什么值。

我也试过 passing data using ExecutionContext,但我不认为这应该在 Spring 批处理作业执行之外工作。

我想知道的是,在执行 Spring 批处理作业之前填充项目并在作业的整个生命周期中维护该对象的最佳方法是什么。

如果最好的方法是我之前所做的尝试之一,欢迎提供有关这些方法常见错误的任何指导,谢谢。

你可以这样做:) 尝试在作业参数增量技巧中做到这一点:

<j:job id="Your_job"  incrementer="incrementerBean">

<bean id="incrementerBean" class="com.whatever.IncrementerClass"/>

递增器class:

class IncrementerClass implements JobParametersIncrementer { 

  @Override
  JobParameters getNext(JobParameters parameters) {

    Map<String, JobParameter> map = new HashMap<String, JobParameter>(
    parameters.getParameters());
    ...
    //you can put here your list, if it can be :
    // Domain representation of a parameter to a batch job. Only the following types
    // can be parameters: String, Long, Date, and Double.

    //make some query 

    List<String> listStrings = Query.getYourQuery();

        //Join your query into string to have something like this below

        map.put("listOfSomething", new JobParameter("abc, abc, abc"));
        ...

     return new JobParameters(map);
  }


}

就是这样, 然后您可以在某些处理 bean 中使用此参数:

  @Value("#{jobParameters['listOfSomething']}")
  private String yourList

您可以从字符串构建列表,仅此而已:) 祝你好运

感谢 Luca Basso RicciJobExecutionListener 指点。我最终创建了自己的 StepExecutionListener 进行预处理的地方。

我关注了 this example from Mkyong,其中介绍了不同类型的 Spring 批处理监听器。

我在 Java 代码中创建了一个像这样的自定义侦听器:

public class CustomStepListener implements StepExecutionListener {

    @Autowired
    private CustomObject customObject;

    @Override
    public void beforeStep(StepExecution stepExecution) {
        // initialize customObject and do other pre set setup
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        return null;
    }

并且我在这里初始化了自动装配 CustomObject class。 CustomObject class 是一个自定义对象,仅包含我的 List 类型 ComplexType

@Component
public class CustomObject {

    private List<ComplexType> customObjectList;

    public List<ComplexType> getCustomObjectList() {
        return customObjectList;
    }

    public void setCustomObjectList(List<ComplexType> customObjectList) {
        this.customObjectList= customObjectList;
    }
}

最后,在我的作业配置中 'batch-job-context.xml' 我添加了我的新侦听器:

<!-- ... -->
<beans:bean id="customStepListener" 
        class="com.robotsquidward.CustomStepListener"/>

<job id="robotsquidwardJob"
    job-repository="jobRepository"
    incrementer="runIdIncrementer">
    <step id="robotsquidwardStep">
        <tasklet task-executor="taskExecutor" throttle-limit="1">
            <chunk 
                reader="robotsquidwardReader" 
                processor="robotsquidwardProcessor"
                writer="robotsquidwardWriter"
                commit-interval="1"/>
        </tasklet>
        <listeners>
            <listener ref="customStepListener"/>
        </listeners>
    </step>
</job>

当我按照这些步骤操作时,我能够在 beforeJob 函数中初始化我的 ComplexObject List 并访问 ComplexObject List 的值在我的工作范围内 Reader class:

@Component
@Scope(value = "step")
public class RobotsquidwardReader implements ItemReader<ComplexType> {

    @Autowired
    private CustomObject customObject;

    @Override
    public ComplexType read() throws Exception, UnexpectedInputException,
            ParseException, NonTransientResourceException {
        if(customObject.getCustomObjectList() != null) {
            return customObject.getCustomObjectList.remove(0);
        } else {
            return null;
        }
    }
}

就这么简单。只需要两个新的 classes、一个配置更改和一个令人头疼的问题:)