在本教程中,我们将向您展示如何配置Spring Batch作业以将XML文件( JAXB2
库)读取到csv
文件中,并在使用ItemProcessor
进行写入之前过滤掉记录。
使用的工具和库
- Maven 3
- Eclipse 4.2
- JDK 1.6
- Spring Core 3.2.2。发布
- Spring Batch 2.2.0。发布
- Spring OXM 3.2.2。发布
PS此示例– XML文件(读取器)–过滤(itemProcessor)– CSV(写入器)。
1.简单的Java项目
1.使用Maven创建一个快速入门Java Project,将其转换并导入Eclipse IDE。
$ mvn archetype:generate -DgroupId=com.mkyong -DartifactId=SpringBatchExample3
-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
$ cd SpringBatchExample3/
$ mvn eclipse:eclipse
2.项目依赖
在pom.xml
声明所有项目依赖项
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mkyong</groupId>
<artifactId>SpringBatchExample</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>SpringBatchExample</name>
<url>http://maven.apache.org</url>
<properties>
<jdk.version>1.6</jdk.version>
<spring.version>3.2.2.RELEASE</spring.version>
<spring.batch.version>2.2.0.RELEASE</spring.batch.version>
</properties>
<dependencies>
<!-- Spring Core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring XML to/back object -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring Batch dependencies -->
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>${spring.batch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-infrastructure</artifactId>
<version>${spring.batch.version}</version>
</dependency>
</dependencies>
<build>
<finalName>spring-batch</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.项目目录结构
查看最终的项目结构,获得下一步的概览。
4. XML文件
<?xml version="1.0" encoding="UTF-8" ?>
<company>
<record refId="1001">
<name>mkyong</name>
<age>31</age>
<dob>31/8/1982</dob>
<income>200,000</income>
</record>
<record refId="1002">
<name>kkwong</name>
<age>30</age>
<dob>26/7/1983</dob>
<income>100,999</income>
</record>
<record refId="1003">
<name>joel</name>
<age>29</age>
<dob>21/8/1984</dob>
<income>1,000,000</income>
</record>
<record refId="1004">
<name>leeyy</name>
<age>29</age>
<dob>21/3/1984</dob>
<income>80,000.89</income>
</record>
</company>
5.读取XML文件
在此示例中,我们使用Jaxb2Marshaller
将XML值和属性映射到对象。
<!-- ...... -->
<bean id="xmlItemReader"
class="org.springframework.batch.item.xml.StaxEventItemReader">
<property name="fragmentRootElementName" value="record" />
<property name="resource" value="classpath:xml/report.xml" />
<property name="unmarshaller" ref="reportUnmarshaller" />
</bean>
<!-- Read and map values to object, via jaxb2 -->
<bean id="reportUnmarshaller"
class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.mkyong.model.Report</value>
</list>
</property>
</bean>
注释Report
以告知哪个XML值映射到哪个字段。
package com.mkyong.model;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import com.mkyong.adapter.JaxbBigDecimalAdapter;
import com.mkyong.adapter.JaxbDateAdapter;
@XmlRootElement(name = "record")
public class Report {
private int refId;
private String name;
private int age;
private Date dob;
private BigDecimal income;
@XmlAttribute(name = "refId")
public int getRefId() {
return refId;
}
public void setRefId(int refId) {
this.refId = refId;
}
@XmlElement(name = "age")
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlJavaTypeAdapter(JaxbDateAdapter.class)
@XmlElement
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
@XmlJavaTypeAdapter(JaxbBigDecimalAdapter.class)
@XmlElement
public BigDecimal getIncome() {
return income;
}
public void setIncome(BigDecimal income) {
this.income = income;
}
// for csv file only
public String getCsvDob() {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
return dateFormat.format(getDob());
}
}
在JAXB2中,那些“复杂”的数据类型(如Date
和BigDecimal
即使被注释,也不会自动映射到该字段。
为了使JAXB2支持Date
转换,您需要创建一个自定义的Adapter来手动处理Date format
,然后通过@XmlJavaTypeAdapter
附加该适配器。
package com.mkyong.adapter;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class JaxbDateAdapter extends XmlAdapter<String, Date> {
private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
@Override
public String marshal(Date date) throws Exception {
return dateFormat.format(date);
}
@Override
public Date unmarshal(String date) throws Exception {
return dateFormat.parse(date);
}
}
与BigDecimal
相同,XML的income元素中的逗号“,”会引起转换问题,您还需要一个自定义适配器来处理它。
package com.mkyong.adapter;
import java.math.BigDecimal;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class JaxbBigDecimalAdapter extends XmlAdapter<String, BigDecimal> {
@Override
public String marshal(BigDecimal obj) throws Exception {
return obj.toString();
}
@Override
public BigDecimal unmarshal(String obj) throws Exception {
return new BigDecimal(obj.replaceAll(",", ""));
}
}
6. Spring批处理核心设置
定义jobRepository
和jobLauncher
。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- stored job-meta in memory -->
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<property name="transactionManager" ref="transactionManager" />
</bean>
<bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
</beans>
7.Spring批作业
Spring批处理作业,读取report.xml
文件,将其映射到Report
对象,并将其写入csv文件。 阅读评论,应该不言自明。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd">
<batch:job id="reportJob">
<batch:step id="step1">
<batch:tasklet>
<batch:chunk reader="xmlItemReader"
writer="cvsFileItemWriter" processor="filterReportProcessor"
commit-interval="1">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<!-- Filtering process -->
<bean id="filterReportProcessor" class="com.mkyong.processor.FilterReportProcessor" />
<bean id="xmlItemReader"
class="org.springframework.batch.item.xml.StaxEventItemReader">
<property name="fragmentRootElementName" value="record" />
<property name="resource" value="classpath:xml/report.xml" />
<property name="unmarshaller" ref="reportUnmarshaller" />
</bean>
<!-- Read and map values to object, via jaxb2 -->
<bean id="reportUnmarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.mkyong.model.Report</value>
</list>
</property>
</bean>
<bean id="cvsFileItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
<!-- write to this csv file -->
<property name="resource" value="file:cvs/report.csv" />
<property name="shouldDeleteIfExists" value="true" />
<property name="lineAggregator">
<bean
class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<property name="delimiter" value="," />
<property name="fieldExtractor">
<bean
class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
<property name="names" value="refId, name, age, csvDob, income" />
</bean>
</property>
</bean>
</property>
</bean>
</beans>
8. Spring Batch – ItemProcessor
在Spring批处理中,将在写入任何资源之前触发有线Processor
,因此,这是处理任何转换,过滤和业务逻辑的最佳位置。 在此示例中,如果Report
对象的age
等于30,则它将被忽略(不写入CSV文件)。
package com.mkyong.processor;
import org.springframework.batch.item.ItemProcessor;
import com.mkyong.model.Report;
//run before writing
public class FilterReportProcessor implements ItemProcessor<Report, Report> {
@Override
public Report process(Report item) throws Exception {
//filter object which age = 30
if(item.getAge()==30){
return null; // null = ignore this object
}
return item;
}
}
9.运行
运行批处理作业的最简单方法。
package com.mkyong;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
String[] springConfig =
{
"spring/batch/config/context.xml",
"spring/batch/jobs/job-report.xml"
};
ApplicationContext context =
new ClassPathXmlApplicationContext(springConfig);
JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean("reportJob");
try {
JobExecution execution = jobLauncher.run(job, new JobParameters());
System.out.println("Exit Status : " + execution.getStatus());
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Done");
}
}
输出。 XML值将插入到csv文件中。
1001,mkyong,31,31/08/1982,200000
1003,joel,29,21/08/1984,1000000
1004,leeyy,29,21/03/1984,80000.89
下载源代码
下载它– SpringBatch-XML-CSV-Example.zip (81 kb)
参考文献
- Spring Batch ItemReaders和ItemWriters
- JAXB自定义绑定– Java.util.Date
- 如何使用FlatFileItemWriter?
- FlatFileItemWriter JavaDoc
翻译自: https://mkyong.com/spring-batch/spring-batch-example-xml-file-to-csv-file/