Spring Batch之复合格式文件的读写

在看本篇博客之前,希望您能先到http://xuanmeiku.taobao.com去转转,里面全是真皮炫美酷时尚女鞋,价格实惠!如果你看中了哪一款,可以加我qq1074992674,或者直接通过旺旺联系我!欢迎大家的骚扰!本人诚信经营,绝不做欺骗他人的事情!


本文主要探讨Spring Batch读取复合格式的数据,然后写入不同的文件的处理方式。

工程结构如下图:

applicationContext.xml文件已经在前面的文章中叙述过。

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

<?xml version="1.0" encoding="UTF-8"?>
<bean:beans xmlns="http://www.springframework.org/schema/batch"
	xmlns:bean="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/batch 
http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
">
	<bean:import resource="applicationContext.xml" />

	<!-- Job信息的配置 -->
	<job id="multiTypeSingleFileJob">
		<step id="multiTypeSingleFileStep">
			<tasklet>
				<chunk reader="multiTypesItemReader" writer="multiTypesItemWriter" commit-interval="1">
					<streams>
						<stream ref="studentWriter"/>
						<stream ref="goodsWriter"/>
					</streams>
				</chunk>
			</tasklet>
		</step>
	</job>
	
	<!-- 不同格式数据的文件读取 -->
	<bean:bean id="multiTypesItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
		<bean:property name="resource" value="file:#{jobParameters['inputFilePath']}"></bean:property>
		<bean:property name="lineMapper">
			<bean:bean class="org.springframework.batch.item.file.mapping.PatternMatchingCompositeLineMapper">
				<bean:property name="tokenizers">
					<bean:map>
						<bean:entry key="student*" value-ref="studentTokenizer"></bean:entry>
						<bean:entry key="goods*" value-ref="goodsTokenizer"></bean:entry>
					</bean:map>
				</bean:property>
				<bean:property name="fieldSetMappers">
					<bean:map>
						<bean:entry key="student*" value-ref="studentFieldSetMapper"></bean:entry>
						<bean:entry key="goods*" value-ref="goodsFieldSetMapper"></bean:entry>
					</bean:map>
				</bean:property>
			</bean:bean>
		</bean:property>
	</bean:bean>
	
	<bean:bean id="studentTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
		<bean:property name="delimiter" value=","></bean:property>
		<bean:property name="names">
			<bean:list>
				<bean:value>student</bean:value>
				<bean:value>ID</bean:value>
				<bean:value>name</bean:value>
				<bean:value>age</bean:value>
				<bean:value>score</bean:value>
			</bean:list>
		</bean:property>
	</bean:bean>
	
	<bean:bean id="studentFieldSetMapper" class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
		<bean:property name="prototypeBeanName" value="student"></bean:property>
		<bean:property name="distanceLimit" value="100"></bean:property>
	</bean:bean>
	
	<!-- 学生Pojo类 -->
	<bean:bean id="student" class="cn.lichunan.springbatch.pojo.Student" scope="prototype"></bean:bean>
	
	<bean:bean id="goodsTokenizer" class="org.springframework.batch.item.file.transform.FixedLengthTokenizer">
		<bean:property name="columns" value="6-13,14-17,18-22,23-32,33-"></bean:property>
		<bean:property name="names" value="isin,quantity,price,customer,buyDay"></bean:property>
	</bean:bean>
	
	<bean:bean id="goodsFieldSetMapper" class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
		<bean:property name="prototypeBeanName" value="goods"></bean:property>
	</bean:bean>
	<!-- 商品Pojo类 -->
	<bean:bean id="goods" class="cn.lichunan.springbatch.pojo.Goods" scope="prototype"></bean:bean>
	
	<bean:bean id="multiTypesItemWriter" class="cn.lichunan.springbatch.writer.MultiItemWriter">
		<bean:property name="delegates">
			<bean:list>
				<bean:ref bean="studentWriter"/>
				<bean:ref bean="goodsWriter"/>
			</bean:list>
		</bean:property>
	</bean:bean>
	
	<!-- 学生信息的写 -->
	<bean:bean id="studentWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
		<bean:property name="resource" value="file:#{jobParameters['outputFilePathStudent']}"></bean:property>
		<bean:property name="lineAggregator">
			<bean:bean class="org.springframework.batch.item.file.transform.FormatterLineAggregator">
				<bean:property name="fieldExtractor">
					<bean:bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
						<bean:property name="names" value="ID,name,age,score"></bean:property>
					</bean:bean>
				</bean:property>
				<bean:property name="format" value="%-9s%-9s%3d%-2.0f"></bean:property>
			</bean:bean>
		</bean:property>
	</bean:bean>
	
	<!-- 商品信息的写 -->
	<bean:bean id="goodsWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
		<bean:property name="resource" value="file:#{jobParameters['outputFilePathGoods']}"></bean:property>
		<bean:property name="lineAggregator">
			<bean:bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
				<bean:property name="fieldExtractor">
					<bean:bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
						<bean:property name="names" value="isin,quantity,price,customer,buyDay"></bean:property>
					</bean:bean>
				</bean:property>
			</bean:bean>
		</bean:property>
	</bean:bean>
	
</bean:beans>
配置了Reader的基本信息。FlatFileItemReader的lineMapper属性使用SpringBatch核心类PatternMatchingCompositeLineMapper的时候,会将读取的记录按照不同的方式映射成我们的Pojo对象。当然首先我们要配置不同的tokenizers和fieldSetMappers,并告诉它当前的记录按照那条原则去解析和映射。我们指定key为student*的时候,用studentTokenizer去解析成fieldset,用studentFieldSetMapper将studentTokenizer解析好的fieldset记录映射成Student对象。我们指定的key,其实也就是student开头的记录,*是通配符。PatternMatchingCompositeLineMapper支持两种通配符:*和?,前者代表多个字符,后者仅代表一个字符。至于student和goods信息如何映射成pojo对象,前面的文章中已经做过详细的介绍,这里就不做赘述了。配置了Writer的基本信息。Writer也是使用代理的方式,学生信息使用定义的studentWriter按照固定长的格式写入学生信息文件中,商品信息使用定义的goodsWriter按照CSV的格式写入商品信息文件中。MultiItemWriter的代码很简单,就不做详细解释了。如下:

package cn.lichunan.springbatch.writer;

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

import org.springframework.batch.item.ItemWriter;

import cn.lichunan.springbatch.pojo.Goods;
import cn.lichunan.springbatch.pojo.Student;

/**
 * 写处理类
 * @author soft
 * @param <T>
 *
 */
public class MultiItemWriter<T> implements ItemWriter<T>{
	
	/**写代理*/
	private List<ItemWriter<? super T>> delegates;
	
	
	public void setDelegates(List<ItemWriter<? super T>> delegates) {
		this.delegates = delegates;
	}

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

}

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

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

      Job启动的代码如下

package cn.lichunan.springbatch.launch;

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 {
			JobExecution result = launcher.run(
					job,
					new JobParametersBuilder()
							.addString(
									"inputFilePath",
									"E:\\workspace-springbatch\\springbatch-MultiTypesSingleFile\\src\\main\\resource\\multiTypesInput.txt")
							.addString(
									"outputFilePathStudent",
									"E:\\workspace-springbatch\\springbatch-MultiTypesSingleFile\\src\\main\\resource\\student.txt")
							.addString(
									"outputFilePathGoods",
									"E:\\workspace-springbatch\\springbatch-MultiTypesSingleFile\\src\\main\\resource\\goods.txt")
							.toJobParameters());
			System.out.println(result.toString());
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}

}

Input文件内容如下:

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
处理结果的学生信息文件如下:

200001   ZhangSan  1878
200002   LiSi      1979
200003   WangWu    2080

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

PNH00101,1000,200.1,zhangshana,Sun Dec 18 01:12:36 CST 2011
PNH00102,2000,300.1,zhangshanb,Mon Dec 19 01:12:36 CST 2011
PNH00103,3000,400.1,zhangshanc,Tue Dec 20 01:12:36 CST 2011


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值