springbatch---->springbatch的使用(七)

  这里我们讲述一下springbatch中关于step层面上面的数据共享技术。而对街的人影都浸染在一片薄荷的白色中,由于无声,都好像经过漂染,不沾人间烟火。

step的数据共享

  关于springbatch里面的step的数据共享,可以有很多的实现方式。比如可以用数据库记载共享的数据、文件保存共享的数据等等。这里我们重点讨论的是springbatch与spring可以解决这类问题的方案。总的来说,可以有如下两种方式。

Execution context
    Use a Spring Batch execution context as a container for user data. A step writes to the execution context; then another step reads from the execution context.
Holder 
    Use a Spring bean and dependency injection. Spring injects a holder bean in the communicating beans. A first step sets values in the holder; another step reads values from the holder.

下面我们针对这同种方式做一个测试的案例。

一、使用Execution context方式共享数据

  • 定义一个job,在batch.xml里面
<job id="shareDataContextJob">
    <step id="setDateStep" next="getDateStep">
        <tasklet transaction-manager="transactionManager" ref="setDataContextTasklet"/>
    </step>
    <step id="getDateStep">
        <tasklet transaction-manager="transactionManager" ref="getDataContextTasklet"/>
    </step>
</job>
  • setDataContextTasklet与getDataContextTasklet的定义
<bean id="setDataContextTasklet" class="spring.batch.shareDataContext.SetDataContextTasklet"/>
<bean id="getDataContextTasklet" class="spring.batch.shareDataContext.GetDataContextTasklet"/>
  • setDataContextTasklet与getDataContextTasklet的实现

存放数据的实现类

package spring.batch.shareDataContext;

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.RepeatStatus;

/**
 * @Author: huhx
 * @Date: 2017-11-02 下午 8:41
 */
public class SetDataContextTasklet implements Tasklet {

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        ExecutionContext jobExecutionContext = chunkContext.getStepContext().
                        getStepExecution().
                        getJobExecution().
                        getExecutionContext();
        jobExecutionContext.putString("username", "huhx");
        System.out.println("set data tasklet.");
        return RepeatStatus.FINISHED;
    }
}

得到数据的实现类

package spring.batch.shareDataContext;

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.RepeatStatus;

/**
 * @Author: huhx
 * @Date: 2017-11-02 下午 8:41
 */
public class GetDataContextTasklet implements Tasklet {

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        ExecutionContext jobExecutionContext = chunkContext.getStepContext().
                getStepExecution().
                getJobExecution().
                getExecutionContext();
        String username = jobExecutionContext.getString("username");
        System.out.println("username = " + username);
        return RepeatStatus.FINISHED;
    }
}

运行的结果,setDateStep得到的getDateStep存放的数据。

set data tasklet.
username = huhx

另外我们还有另外一种写法。在基于上述的代码做如下的修改:getDataContextTasklet和定义与实现。注意scope="step"是必须的。

<bean id="getDataContextTasklet" class="spring.batch.shareDataContext.GetDataContextTasklet" scope="step">
    <property name="username" value="#{jobExecutionContext['username']}"/>
</bean>

 getDataContextTasklet的实现类,可以直接注入username得到setDataContextTasklet里面设置的username值。

package spring.batch.shareDataContext;

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.RepeatStatus;

/**
 * @Author: huhx
 * @Date: 2017-11-02 下午 8:41
 */
public class GetDataContextTasklet implements Tasklet {
    private String username;

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        System.out.println("username = " + username);
        return RepeatStatus.FINISHED;
    }
}

二、通过Spring holder beans共享数据

  • 定义一个job,在batch.xml中
<job id="shareDataHolderJob">
    <step id="setDateHolderStep" next="getDateHolderStep">
        <tasklet transaction-manager="transactionManager" ref="setDataHolderTasklet"/>
    </step>
    <step id="getDateHolderStep">
        <tasklet transaction-manager="transactionManager" ref="getDataHolderTasklet"/>
    </step>
</job>
  • setDataHolderTasklet、getDataHolderTasklet以及共享数据Bean类的定义
<!--通过holder分享数据-->
<bean id="importMetadata" class="spring.batch.shareDataHolder.ImportMetadataHolder"/>
<bean id="setDataHolderTasklet" class="spring.batch.shareDataHolder.SetDataHolderTasklet"> <property name="importMetadataHolder" ref="importMetadata"/> </bean> <bean id="getDataHolderTasklet" class="spring.batch.shareDataHolder.GetDataHolderTasklet"> <property name="importMetadataHolder" ref="importMetadata"/> </bean>
  • 上述xml定义的bean类的实现

ImportMetadataHolder:共享数据Bean类。

package spring.batch.shareDataHolder;

import spring.batch.readFile.People;

/**
 * @Author: huhx
 * @Date: 2017-11-03 上午 8:56
 */
public class ImportMetadataHolder {
    private People people;

    public People getPeople() {
        return people;
    }

    public void setPeople(People people) {
        this.people = people;
    }
}

SetDataHolderTasklet:设置共享数据的实现类

package spring.batch.shareDataHolder;

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import spring.batch.readFile.People;

import java.util.Date;

/**
 * @Author: huhx
 * @Date: 2017-11-03 上午 9:00
 */
public class SetDataHolderTasklet implements Tasklet {
    private ImportMetadataHolder importMetadataHolder;

    public void setImportMetadataHolder(ImportMetadataHolder importMetadataHolder) {
        this.importMetadataHolder = importMetadataHolder;
    }

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        People people = new People();
        people.setUsername("huhx");
        people.setBirthday(new Date());
        people.setAddress("武汉");
        people.setAge(23);
        importMetadataHolder.setPeople(people);
        return RepeatStatus.FINISHED;
    }
}

GetDataHolderTasklet:获取共享数据的实现类

package spring.batch.shareDataHolder;

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

/**
 * @Author: huhx
 * @Date: 2017-11-03 上午 9:00
 */
public class GetDataHolderTasklet implements Tasklet {
    private ImportMetadataHolder importMetadataHolder;

    public void setImportMetadataHolder(ImportMetadataHolder importMetadataHolder) {
        this.importMetadataHolder = importMetadataHolder;
    }

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        System.out.println(importMetadataHolder.getPeople());
        return RepeatStatus.FINISHED;
    }
}

运行的结果,在控制台打印:

username=huhx|age=23|address=武汉|birthday=Fri Nov 03 09:06:24 CST 2017

之所以ImportMetadataHolder类能够共享,是由于spring中Bean的默认scope是singleton单例的。如果修改scope为prototype。那么输出的结果为null。

另外这种方式也可以使用SpEL表达式的方式来注入要共享的数据。修改getDataHolderTasklet的定义和实现类以及修改importMetadata的scope=singleton。如下

<bean id="getDataHolderTasklet" class="spring.batch.shareDataHolder.GetDataHolderTasklet" scope="step">
    <property name="username" value="#{importMetadata.getPeople().getUsername()}"/>
</bean>

GetDataHolderTasklet可以直接注入username,打印它的结果为huhx。这里就不贴出代码。

友情链接

原文地址:https://www.cnblogs.com/huhx/p/baseusespringbatch7.html