【问题标题】:Controlling Spring-Batch Step Flow in a java-config manner以 java-config 方式控制 Spring-Batch Step Flow
【发布时间】:2014-02-17 21:04:05
【问题描述】:

根据 Spring-Batch 文档 (http://docs.spring.io/spring-batch/2.2.x/reference/html/configureStep.html#controllingStepFlow),在 xml 配置文件中控制步骤流程非常简单:

例如我可以编写以下作业配置:

<job id="myJob">
    <step id="step1">
        <fail on="CUSTOM_EXIT_STATUS"/>
        <next on="*" to="step2"/>
    </step>

    <step id="step2">
        <end on="1ST_EXIT_STATUS"/>
        <next on="2ND_EXIT_STATUS" to="step10"/>
        <next on="*" to="step20"/>
    </step>

    <step id="step10" next="step11" />
    <step id="step11" />

    <step id="step20" next="step21" />
    <step id="step21" next="step22" />
    <step id="step22" />
</job>

有没有简单的方法以 java-config 的方式定义这样的作业配置? (使用 JobBuilderFactory 等...)

【问题讨论】:

    标签: spring spring-batch spring-java-config


    【解决方案1】:

    正如文档中还提到的,我们只能根据步骤的退出状态对流程进行分支。为了能够报告自定义退出状态(可能不同于从批处理状态自动映射的退出状态),我们必须为StepExecutionListener 提供afterStep 方法。

    假设我们有一个初始步骤step1(Tasklet 类Step1 的一个实例),我们想要执行以下操作:

    • 如果step1 失败(例如通过抛出运行时异常),那么整个作业应该被视为FAILED。
    • 如果step1 以COMPLETED-WITH-A 的退出状态完成,那么我们想要分支到某个步骤step2a,它应该可以处理这种特定情况。
    • 否则,我们将留在工作的主卡车上并继续执行步骤step2。

    现在,在Step1 类中提供一个afterStep 方法(同时实现StepExecutionListener):

    private static class Step1 implements Tasklet, StepExecutionListener
    {
        @Override
        public ExitStatus afterStep(StepExecution stepExecution)
        {
            logger.info("*after-step1* step-execution={}", stepExecution.toString());
    
            // Report a different exit-status on a random manner (just a demo!).
            // Some of these exit statuses (COMPLETED-WITH-A) are Step1-specific 
            // and are used to base a conditional flow on them.
    
            ExitStatus exitStatus = stepExecution.getExitStatus();
            if (!"FAILED".equals(exitStatus.getExitCode())) {
                double r = Math.random(); 
                if (r < 0.50)
                    exitStatus = null; // i.e. COMPLETED
                else 
                    exitStatus = new ExitStatus(
                        "COMPLETED-WITH-A", 
                        "Completed with some special condition A");
            }
            logger.info("*after-step1* reporting exit-status of {}", exitStatus);
            return exitStatus;
        }
    
        // .... other methods of Step1
    }
    

    最后,在我们的JobFactory 实现的createJob 方法中构建工作流:

    @Override
    public Job createJob()
    {
        // Assume some factories returning instances of our Tasklets
        Step step1 = step1(); 
        Step step2a = step2a();
        Step step2 = step2();
    
        JobBuilder jobBuilder = jobBuilderFactory.get(JOB_NAME)
            .incrementer(new RunIdIncrementer())
            .listener(listener);  // a job-level listener
    
        // Build job flow
        return jobBuilder
            .start(step1)
                .on("FAILED").fail()
            .from(step1)
                .on("COMPLETED-WITH-A").to(step2a)
            .from(step1)
            .next(step2)
            .end()
            .build();
    }
    

    【讨论】:

      【解决方案2】:

      也许吧。如果您的意图是“以编程方式”(使用 SB 的框架接口,我的意思是)编写类似于流决定器的东西,那么有内置的实现,对于大多数用例来说已经足够了。

      与 XML 配置相反,如果您熟悉 JavaConfig 注释,则可以使用它们;我个人更喜欢 XML 定义,但这只是个人意见。

      【讨论】:

        猜你喜欢
        • 2017-07-28
        • 2015-12-10
        • 2016-08-31
        • 1970-01-01
        • 1970-01-01
        • 2016-09-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多