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


  這里我們重點學習一下springbatch里面的各種監聽器的使用,以及job參數的傳遞。追求得到之日即其終止之時,尋覓的過程亦即失去的過程。

 

springbatch的監聽器

一、JOB LISTENERS:監聽job層面上的操作

public interface JobExecutionListener {
    void beforeJob(JobExecution jobExecution);
    void afterJob(JobExecution jobExecution);
}
  • 類方法的方式
<job id="helloWorldJob">
    <listeners>
        <listener ref="jobExecListener"/>
    </listeners>
    <step ....>
    </step>
</job>

bean的定義

<bean id="jobExecListener" class="spring.batch.helloworld.JobExecListener"/>

 bean的實現

package spring.batch.helloworld;

import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;

/**
 * @Author: huhx
 * @Date: 2017-11-02 上午 8:50
 */
public class JobExecListener implements JobExecutionListener {

    @Override
    public void beforeJob(JobExecution jobExecution) {
        System.out.println("before start time: " + jobExecution.getStartTime());
    }

    @Override
    public void afterJob(JobExecution jobExecution) {
        System.out.println("after end time: " + jobExecution.getEndTime());
    }
}
  • 使用注解方式,區別在於bean類的編寫。
public class JobExecListener {

    @BeforeJob
    public void beforeJob(JobExecution jobExecution) {
        System.out.println("before start time: " + jobExecution.getStartTime());
    }

    @AfterJob
    public void afterJob(JobExecution jobExecution) {
        System.out.println("after end time: " + jobExecution.getEndTime());
    }
}

這個例子是基於helloworld的例子來的,可以參考博客:springbatch---->springbatch的使用(一).。以下是打印的結果

before start time: Thu Nov 02 09:00:13 CST 2017
Hello 
 World!
after end time: Thu Nov 02 09:00:14 CST 2017

 

二、STEP LISTENERS:監聽Step的處理過程

springbatch為我們提供了如下的關於Step的監聽器。

1、ChunkListener 
    Called before and after chunk execution
2、ItemProcessListener 
    Called before and after an ItemProcessor gets an item and when that processor throws an exception
3、ItemReadListener 
    Called before and after an item is read and when an
exception occurs reading an item
4、ItemWriteListener 
    Called before and after an item is written and when an exception occurs writing an item
5、SkipListener 
    Called when a skip occurs while reading, processing, or writing an item
6、StepExecutionListener 
    Called before and after a step

Step監聽器的接口,用法同上述的Job監聽器基本一樣。也是有方法的實現方式和注解的實現方式。

 

三、parent與abstract屬性的使用

1、abstract 
    When  true, specifies that the job or step element isn’t a concrete element but an abstract one used only for configuration. Abstract configuration enti-
ties aren’t instantiated.
2、parent: 子元素繼承了父元素所有的屬性,當然子元素可以復寫父元素的屬性
    The parent element used to configure a given element. The child element has all properties of its parent and can override them.

 在batch.xml文件中增加一個step和一個job。

<!--parent and abstract-->
<step id="parentStep" abstract="true">
    <tasklet transaction-manager="transactionManager">
        <listeners>
            <listener ref="parentStepListener"/>
        </listeners>
    </tasklet>
</step>

<job id="childJob">
    <step id="childStep" parent="parentStep">
        <tasklet ref="childTasklet" transaction-manager="transactionManager"/>
    </step>
</job>

<bean:bean id="childTasklet" class="spring.batch.parentAbstract.ParentTasklet" scope="step">
    <bean:property name="username" value="#{jobParameters['password']}"/>
</bean:bean>

  parentTasklet的實現類代碼:

package spring.batch.parentAbstract;

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-02 上午 9:18
 */
public class ParentTasklet 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("parent tasklet" + username);
        return RepeatStatus.FINISHED;
    }
}

打印的結果如下,可以看到childJob已經有了parentStep里面的監聽器了。

before step.
parent tasklet123456
after step.

 另外JobLaunch.java的代碼如下

public class JobLaunch {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("config/batch/batch.xml");
        JobLauncher launcher = (JobLauncher) context.getBean("jobLauncher");

        Job job = (Job) context.getBean("childJob");
        try {
            // 運行Job
            JobParametersBuilder parametersBuilder = new JobParametersBuilder();
            JobParameters jobParameters = parametersBuilder.
                    addString("username", "linux").
                    addString("password", "123456").
                    toJobParameters();
            launcher.run(job, jobParameters);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

有關於scope="step" 的解釋,這里說明一下。

    The step scope means that Spring will create the bean only when the step asks for it and that values will be resolved then (this is the lazy instantiation pattern; the bean isn’t created during the Spring application context’s bootstrapping). To trigger the dynamic evaluation of a value, you must use the #{expression} syntax. The expression must be in Sp EL , which is available as of Spring 3.0.

 

四、關於ValidatingItemProcessor的一些理解

  它實現了ItemProcessor,用於chunk里面的processor屬性。以下是它的一個用法。Simple implementation of ItemProcessor that validates input and returns it without modifications.

...
<batch:chunk reader="reader" processor="processor" writer="writer" commit-interval="100" skip-limit="5">
    <batch:skippable-exception-classes>
        <batch:include class="org.springframework.batch.item.validator.ValidationException"/>
    </batch:skippable-exception-classes>
</batch:chunk>
....

<bean id="processor" class="org.springframework.batch.item.validator.ValidatingItemProcessor">
    <property name="filter" value="false" />
    <property name="validator">
        <bean class="spring.batch.parentAbstract.ProductValidator" />
    </property>
</bean>

ProductValidator的代碼

import java.math.BigDecimal;
import org.springframework.batch.item.validator.ValidationException;
import org.springframework.batch.item.validator.Validator;
import com.manning.sbia.ch01.domain.Product;

public class ProductValidator implements Validator<Product> {
    @Override
    public void validate(Product product) throws ValidationException {
        if(BigDecimal.ZERO.compareTo(product.getPrice()) >= 0) {
            throw new ValidationException("Product price cannot be negative!");
        }
    }
}

關於ValidatingItemProcessor的源代碼,它有兩個屬性validator和filter 。

package org.springframework.batch.item.validator;

import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

public class ValidatingItemProcessor<T> implements ItemProcessor<T, T>, InitializingBean {

    private Validator<? super T> validator;

    private boolean filter = false;

    public ValidatingItemProcessor() {}

    public ValidatingItemProcessor(Validator<? super T> validator) {
        this.validator = validator;
    }

    public void setValidator(Validator<? super T> validator) {
        this.validator = validator;
    }

    public void setFilter(boolean filter) {
        this.filter = filter;
    }

    @Override
    public T process(T item) throws ValidationException {
        try {
            validator.validate(item);
        }
        catch (ValidationException e) {
            if (filter) {
                return null; // filter the item
            }
            else {
                throw e; // skip the item
            }
        }
        return item;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(validator, "Validator must not be null.");
    }
}

 

友情鏈接

 


免責聲明!

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



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