Spring Batch 之 Sample(复合格式文件的读、多文件的写)(七)

转自:http://www.cnblogs.com/gulvzhe/archive/2011/12/18/2291570.html

前面关于Spring Batch的文章,讲述了SpringBatch对CSV文件的读写操作、对XML文件的操作,以及对固定长格式文件的操作。这些事例,同一个Reader读取的都是相同格式的数据,最终写入一个文件。如果遇到下面这样的数据,并想将学生信息和商品信息分类后写入两个文件,应该如何处理呢?

student,200001,ZhangSan,18,78
goodsPNH001011000200.1zhangshana2011/12/18 01:12:36
student,200002,LiSi,19,79
goodsPNH001022000300.1zhangshanb2011/12/19 01:12:36
student,200003,WangWu,20,80
goodsPNH001033000400.1zhangshanc2011/12/20 01:12:36

  * 以student开头的数据代表学生信息,以goods开头代表商品信息

这次将和大家一起探讨Spring Batch读取复合格式的数据,然后写入不同的文件的处理方式。

      工程结构如下图:

       applicationContext.xml和log4j.xml前文已经叙述过,在此不做赘述。

      本实例的核心配置文件batch.mxl内容如下:




    
    
    
        
            
                
                    
                        
                        
                    
                
            
        
    

    
    
        
        
            
                
                    
                        
                        
                    
                
                
                    
                        
                        
                    
                
            
        
    
    
        
        
            
                student
                ID
                name
                age
                score
            
        
    
    
        
        
    
    
    

    
        
        
    
    
        
    
    
    

    
        
            
                
                
            
        
    
    
    
        
        
            
                
                    
                        
                    
                
                
            
        
    
    
    
        
        
            
                
                    
                        
                    
                
            
        
    


       21-33行配置了Job的基本信息。  

      36-57行配置了Reader的基本信息。FlatFileItemReader的lineMapper属性使用SpringBatch核心类PatternMatchingCompositeLineMapper的时候,会将读取的记录按照不同的方式映射成我们的Pojo对象。当然首先我们要配置不同的tokenizers(43-48)和fieldSetMappers(49-54),并告诉它当前的记录按照那条原则去解析和映射。如45行所示,我们指定key为student*的时候,用studentTokenizer去解析成fieldset,用studentFieldSetMapper将studentTokenizer解析好的fieldset记录映射成Student对象。我们指定的key,其实也就是student开头的记录,*是通配符。PatternMatchingCompositeLineMapper支持两种通配符:*和?,前者代表多个字符,后者仅代表一个字符。至于student和goods信息如何映射成pojo对象,前面的文章中已经做过详细的介绍,这里就不做赘述了。

      96-104行配置了Writer的基本信息。Writer也是使用代理的方式,学生信息使用106-122行定义的studentWriter按照固定长的格式写入学生信息文件中,商品信息使用124-141行定义的goodsWriter按照CSV的格式写入商品信息文件中。MultiItemWriter的代码很简单,就不做详细解释了。如下:

package com.wanggc.springbatch.sample.multitypessinglefile;

import java.util.ArrayList;
import java.util.List;

import org.springframework.batch.item.ItemWriter;

import com.wanggc.springbatch.sample.multitypessinglefile.pojo.Goods;
import com.wanggc.springbatch.sample.multitypessinglefile.pojo.Student;

/**
 * 写处理类。
 * 
 * @author Wanggc
 * 
 * @param 
 */
@SuppressWarnings("unchecked")
public class MultiItemWriter implements ItemWriter {
    /** 写代理 */
    private List> delegates;

    public void setDelegates(List> delegates) {
        this.delegates = delegates;
    }

    @Override
    public void write(List items) throws Exception {
        // 学生信息的Writer
        ItemWriter studentWriter = (ItemWriter) delegates.get(0);
        // 商品信息的Writer
        ItemWriter goodsWriter = (ItemWriter) delegates.get(1);
        // 学生信息
        List studentList = new ArrayList();
        // 商品信息
        List goodsList = new ArrayList();
        // 将传过来的信息按照不同的类型添加到不同的List中
        for (int i = 0; i < items.size(); i++) {
            if ("Student".equals(items.get(i).getClass().getSimpleName())) {
                studentList.add((Student) items.get(i));
            } else {
                goodsList.add((Goods) items.get(i));
            }
        }
        // 如果学生List中有数据,就执行学生信息的写
        if (studentList.size() > 0) {
            studentWriter.write(studentList);
        }
        // 如果商品List中有数据,就执行商品信息的写
        if (goodsList.size() > 0) {
            goodsWriter.write(goodsList);
        }
    }
}


      至此,复合文件的读写操作已经讨论结束了。注意实例没有配置Processor。下面是一些辅助文件的信息。

      student和goods类的信息与前面文章一样,就不再贴出代码了。

      Job启动的代码如下:

package com.wanggc.springbatch.sample.multitypessinglefile;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Launch {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "batch.xml");
        JobLauncher launcher = (JobLauncher) context.getBean("jobLauncher");
        Job job = (Job) context.getBean("multiTypeSingleFileJob");

        try {
            // JOB实行
            JobExecution result = launcher.run(
                    job,
                    new JobParametersBuilder()
                            .addString("inputFilePath",
                                    "C:\\testData\\multiTypesInput.txt")
                            .addString("outputFilePathStudent",
                                    "C:\\testData\\student.txt")
                            .addString("outputFilePathGoods",
                                    "C:\\testData\\goods.csv")
                            .toJobParameters());
            // 运行结果输出
            System.out.println(result.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


      Input文件内容如下图:

      处理结果的学生信息文件如下图:

     处理结果的商品信息文件如下图:

      Spring Batch对复合格式文件的读写操作就讨论到这里。至此,Spring Batch对文件简单操作的讨论也告一段落,下次将讨论Spring Batch读写DB的操作。


你可能感兴趣的:(spring-batch)