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。這里就不貼出代碼。

 

友情鏈接

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM