介绍
用Spring Batch实现一个简单的需求,将csv文件转换成xml文件。
csv文件如下:record.csv
username, user_id, transaction_date, transaction_amount
devendra, 1234, 31/10/2015, 10000
john, 2134, 3/12/2015, 12321
robin, 2134, 2/02/2015, 23411
转换成的xml文件如下:record.xml
<?xml version="1.0" encoding="UTF-8"?><transactionRecord>
<transactionRecord>
<amount>10000.0</amount>
<transactionDate>2015-10-31T00:00:00+08:00</transactionDate>
<userId>1234</userId>
<username>devendra</username>
</transactionRecord>
<transactionRecord>
<amount>12321.0</amount>
<transactionDate>2015-12-03T00:00:00+08:00</transactionDate>
<userId>2134</userId>
<username>john</username>
</transactionRecord>
<transactionRecord>
<amount>23411.0</amount>
<transactionDate>2015-02-02T00:00:00+08:00</transactionDate>
<userId>2134</userId>
<username>robin</username>
</transactionRecord>
实现
下面用Spring Batch实现,思路很简单,定义一个Reader读record.csv,定义一个Writer写record.xml
用Java来配置
SpringConfig.java,部分代码
// 数据源
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.sqlite.JDBC");
dataSource.setUrl("jdbc:sqlite:repository.sqlite");
return dataSource;
}
// 事务管理器
private PlatformTransactionManager getTransactionManager() {
return new ResourcelessTransactionManager();
}
// 任务仓库
private JobRepository getJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource());
factory.setTransactionManager(getTransactionManager());
// JobRepositoryFactoryBean's methods Throws Generic Exception,
// it would have been better to have a specific one
factory.afterPropertiesSet();
return (JobRepository) factory.getObject();
}
// 任务加载器
public JobLauncher getJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
// SimpleJobLauncher's methods Throws Generic Exception,
// it would have been better to have a specific one
jobLauncher.setJobRepository(getJobRepository());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
创建DTO对象
创建一个Transaction.java用来传输record.csv中的每行数据
package com.yysue.batch.demo01.model;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
@SuppressWarnings("restriction")
@XmlRootElement(name = "transactionRecord")
public class Transaction {
private String username;
private int userId;
private Date transactionDate;
private double amount;
// get/set...
}
定义ItemReader
@Bean
public ItemReader<Transaction> itemReader() throws UnexpectedInputException, ParseException {
// 数据来源
Resource inputCsv = new ClassPathResource("demo01/input/record.csv");
// Spring Batch的内置reader
FlatFileItemReader<Transaction> reader = new FlatFileItemReader<>();
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
String[] tokens = {"username", "userid", "transactiondate", "amount"};
tokenizer.setNames(tokens);
reader.setResource(inputCsv);
DefaultLineMapper<Transaction> lineMapper = new DefaultLineMapper<Transaction>();
lineMapper.setLineTokenizer(tokenizer);
lineMapper.setFieldSetMapper(new RecordFieldSetMapper());
reader.setLinesToSkip(1); // 文件开头需要忽略的行数
reader.setLineMapper(lineMapper);
return reader;
}
定义ItemWriter
@Bean
public ItemWriter<Transaction> itemWriter(Marshaller marshaller) throws MalformedURLException {
String userHome = System.getProperty("user.home");
Resource outputXml = new FileSystemResource(userHome + "/output/demo01/record.xml");
StaxEventItemWriter<Transaction> itemWriter = new StaxEventItemWriter<Transaction>();
itemWriter.setMarshaller(marshaller);
itemWriter.setRootTagName("transactionRecord");
itemWriter.setResource(outputXml);
return itemWriter;
}
定义Processor
@Bean
public ItemProcessor<Transaction, Transaction> itemProcessor() {
return new CustomItemProcessor();
}
定义Job和Step
@Bean
protected Step step1(ItemReader<Transaction> reader, ItemProcessor<Transaction, Transaction> processor, ItemWriter<Transaction> writer) {
return steps.get("step1")
.<Transaction, Transaction>chunk(10)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
@Bean(name = "firstBatchJob")
public Job job(@Qualifier("step1") Step step1) {
return jobs.get("firstBatchJob").start(step1).build();
}
定义主程序
App.java
public static void main(final String[] args) {
// Spring Java config
final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(SpringConfig.class);
context.register(SpringBatchConfig.class);
context.refresh();
// Spring xml config
// ApplicationContext context = new ClassPathXmlApplicationContext("demo01/spring-batch.xml");
final JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
final Job job = (Job) context.getBean("firstBatchJob");
System.out.println("Starting the batch job");
try {
final JobExecution execution = jobLauncher.run(job, new JobParameters());
System.out.println("Job Status : " + execution.getStatus());
System.out.println("Job succeeded");
} catch (final Exception e) {
e.printStackTrace();
System.out.println("Job failed");
}
System.exit(0);
}
运行主程序,会读取项目的resources/demo01/input/record.csv文件,在用户目录下生成文件 xml文件为:output/demo01/record.xml
总结
本例完整实现 spring-batch