【问题标题】:Maintain pre-job object through Spring Batch job steps通过 Spring Batch 作业步骤维护作业前对象
【发布时间】:2016-06-02 20:48:04
【问题描述】:

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

我已尝试在我的列表中自动装配并在步骤中访问它,但我无法以这种方式访问​​列表中的数据。无论在作业之前已将什么值添加到我的自动装配的 List 属性中,我的 List 中都会得到一个 null ComplexType。

我也尝试过passing data using ExecutionContext,但我认为这不应该在 Spring Batch 作业执行之外起作用。

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

如果最好的方法是我之前所做的尝试之一,那么对于这些​​方法的常见错误的任何指导表示赞赏,谢谢。

【问题讨论】:

  • stackoverflow.com/questions/34680189/…。检查有问题的 cmets,而不是答案
  • 将您需要存储的任何内容存储在作业侦听器 (@BeforeJob) 中并将其注入阅读器...不要试图让您的生活过于复杂:D

标签: java spring list spring-batch autowired


【解决方案1】:

感谢Luca Basso Ricci 提供JobExecutionListener 指针。我最终创建了自己的StepExecutionListener,我的预处理将在其中进行。

我关注了this example from Mkyong,它涵盖了不同类型的 Spring Batch 侦听器。

我在 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 类。 CustomObject 类是一个自定义对象,它只包含我的 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 并在我工作的 Reader 类中访问 ComplexObject List 的值:

@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;
        }
    }
}

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

【讨论】:

    【解决方案2】:

    你可以这样做:) 尝试在作业参数增量器技巧中执行此操作:

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

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

    增量器类:

    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
    

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-30
    • 1970-01-01
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    • 2019-01-04
    • 2020-03-06
    相关资源
    最近更新 更多