Spring Batch 之 Sample(XML文件操作)(五)

 前篇關於Spring Batch的文章,講述了Spring Batch 對CSV文件的讀寫操作。 本文將通過一個完整的實例,與大家一起討論運用Spring Batch對XML文件的讀寫操作。實例流程是從一個XML文件中讀取商品信息,經過簡單的處理,寫入另外一個XML文件中。

     工程結構如下圖:

                       

     log4j.xml是log處理的配置文件,與本文沒有必然聯繫,再此不做論述。

     application.xml文件內容如下:

 1<?xml version="1.0" encoding="UTF-8"?>
2<beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
4 xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
5 xmlns:context="http://www.springframework.org/schema/context"
6 xsi:schemaLocation="http://www.springframework.org/schema/beans
7http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
8http://www.springframework.org/schema/tx
9http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
10http://www.springframework.org/schema/aop
11http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
12http://www.springframework.org/schema/context
13http://www.springframework.org/schema/context/spring-context-2.5.xsd"
14 default-autowire="byName">
15
16<!-- auto scan path -->
17<context:component-scan base-package="com.wanggc.springbatch.sample.xml"/>
18
19<bean id="jobLauncher"
20 class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
21<property name="jobRepository" ref="jobRepository"/>
22</bean>
23
24<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"/>
25
26<bean id="transactionManager"
27 class="org.springframework.batch.support.transaction.ResourcelessTransactionManager">
28</bean>
29</beans>

     17行是base-spckage的指定,是spring的用法。

     19-22行配置的jobLauncher用來啓動Job。

     24行配置的jobRepository爲job提供持久化操作。

     26-28行的transactionManager提供事物管理操作。

     本文核心配置文件batch.xml內容如下:

 1<?xml version="1.0" encoding="UTF-8"?>
2<bean:beans xmlns="http://www.springframework.org/schema/batch"
3 xmlns:bean="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
5 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
6 xmlns:util="http://www.springframework.org/schema/util"
7 xsi:schemaLocation="http://www.springframework.org/schema/beans
8http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
9http://www.springframework.org/schema/tx
10http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
11http://www.springframework.org/schema/aop
12http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
13http://www.springframework.org/schema/context
14http://www.springframework.org/schema/context/spring-context-2.5.xsd
15http://www.springframework.org/schema/batch
16http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
17http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
18
19<bean:import resource="applicationContext.xml"/>
20
21<job id="xmlFileReadAndWriterJob">
22<step id="xmlFileReadAndWriterStep">
23<tasklet>
24<chunk reader="xmlReader" writer="xmlWriter" processor="xmlProcessor"
25 commit-interval="10">
26</chunk>
27</tasklet>
28</step>
29</job>
30
31<!-- XML文件讀取 -->
32<bean:bean id="xmlReader"
33 class="org.springframework.batch.item.xml.StaxEventItemReader" scope="step">
34<bean:property name="fragmentRootElementName" value="goods"/>
35<bean:property name="unmarshaller" ref="tradeMarshaller"/>
36<bean:property name="resource"
37 value="file:#{jobParameters['inputFilePath']}"></bean:property>
38</bean:bean>
39
40<!-- XML文件寫入 -->
41<bean:bean id="xmlWriter"
42 class="org.springframework.batch.item.xml.StaxEventItemWriter" scope="step">
43<bean:property name="rootTagName" value="wanggc"/>
44<bean:property name="marshaller" ref="tradeMarshaller"/>
45<bean:property name="resource"
46 value="file:#{jobParameters['outputFilePath']}"/>
47</bean:bean>
48
49<bean:bean id="tradeMarshaller"
50 class="org.springframework.oxm.xstream.XStreamMarshaller">
51<bean:property name="aliases">
52<util:map id="aliases">
53<bean:entry key="goods"
54 value="com.wanggc.springbatch.sample.xml.pojo.Goods"/>
55<bean:entry key="buyDay" value="java.util.Date"></bean:entry>
56</util:map>
57</bean:property>
58</bean:bean>
59</bean:beans>

     21-29行配置了Job的基本信息。此Job包含一個Step,Step中包含了基本的讀(xmlReader),處理(xmlProcessor),寫(xmlWriter)。

     32-38行配置了對XML文件讀操作。對XML的讀是由SpringBatch提供的StaxEventItemReader類來完成。要讀取一個XML文件,首先要知道這個文件的存放路徑,resource屬性就是指定文件路徑信息的。知道了文件路徑,還需要知道要讀取的XML的根節點名稱,fragmentRootElementName屬性就是指定根節點名稱的。知道了根節點名稱,還需要知道的一點就是怎麼解析這個節點信息,unmarshaller就負責完成解析節點信息,並映射成程序pojo對象。注意,根節點並不是指整個XML文件的根節點,而是指要讀取的信息片段的根節點,不管這個節點片段處在哪一層,框架都會遍歷到。

     49-58行配置瞭解析XML節點信息的unmarshaller。其中entry的key指定對應根節點名稱goods,value指定程序的pojo類,這樣,程序就可以將goods節點下的子節點與pojo類(Goods)中的屬性去匹配,當匹配到子節點名與pojo類中的屬性名相同時,就會將子節點的內容賦值給pojo類的屬性。這樣就完成了一個根節點的讀取,框架會控制循環操作,直到將文件中所有根(goods)節點全部讀完爲止。這樣就完成了XML文件的讀操作。

     41-47行配置了對XML文件的寫操作。與讀XML文件一樣,要寫一個XML文件,也是需要知道這個文件的文件的存放路徑的,同樣是resource屬性提供文件的路徑信息。同時,也是需要知道這個文件的跟節點信息的,rootTagName屬性提供根節點名信息。注意此處的根節點,指整個文件的跟節點,與讀得時候稍有區別,從兩個屬性的名稱上也可以看出。有了上面的信息,完成一個寫操作,還需要一個把pojo對象轉換成XML片段的工具,由marshaller提供。本文讀操作的unmarshaller和寫操作的marshaller用的是同一個轉換器,因爲XStreamMarshaller既提供將節點片段轉換爲pojo對象功能,同時又提供將pojo對象持久化爲xml文件的功能。如果寫的內容與讀得內容有很大差異,可以另外配置一個轉換器。

     batch.xml文件配置的對XML文件的讀寫操作,至於讀出來的信息做怎麼樣的處理再寫入文件,通過簡單的配置恐怕就無法完成了,就需要我們自己寫代碼完成了。XMLProcessor類就是完成這個工作的。只要在Job的配置文件中指定到這個類就可以了。XMLProcessor類的內容如下:

package com.wanggc.springbatch.sample.xml;

import java.util.Date;

import org.springframework.batch.item.ItemProcessor;
import org.springframework.stereotype.Component;

import com.wanggc.springbatch.sample.xml.pojo.Goods;

/**
* XML文件處理類。
*/
@Component("xmlProcessor")
publicclass XMLProcessor implements ItemProcessor<Goods, Goods> {

/**
* XML文件內容處理。
*
*/
@Override
public Goods process(Goods goods) throws Exception {
// 購入日期變更
goods.setBuyDay(new Date());
// 顧客信息變更
goods.setCustomer(goods.getCustomer() + "顧客!");
// ISIN變更
goods.setIsin(goods.getIsin() + "IsIn");
// 價格變更
goods.setPrice(goods.getPrice() + 1000.112);
// 數量變更
goods.setQuantity(goods.getQuantity() + 100);
// 處理後的數據返回
return goods;
}
}

     內容很簡單,再此就不做贅述了。要注意的一點就是紅背景色的地方。加了此標籤無須在batch.xml文件增加對xmlProcessor聲明用的bean,可以在job中直接引用,這是Spring的功能。當然,實現這個的前提是要在applicationContext.xml中配置base-package,只有這樣才能找到。

     工程結構圖中的XMLLaunch類用來啓動Job。內容如下:

package com.wanggc.springbatch.sample.xml;

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;

publicclass XMLLaunch {

/**
*
@param args
*/
publicstaticvoid main(String[] args1) {

ApplicationContext context = new ClassPathXmlApplicationContext(
"batch.xml");
JobLauncher launcher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean("xmlFileReadAndWriterJob");

try {
// JOB實行
JobExecution result = launcher.run(job, new JobParametersBuilder()
.addString("inputFilePath", "C:\\input.xml")
.addString("outputFilePath", "C:\\output.xml")
.toJobParameters());
// 運行結果輸出
System.out.println(result.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}

注意其中爲Job提供的兩個動態參數,以及在配置文件中的用法。

      pojo類Goods的內容如下:

package com.wanggc.springbatch.sample.xml.pojo;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* 商品信息類.
*/
publicclass Goods {
/** isin號 */
private String isin;
/** 數量 */
privateint quantity;
/** 價格 */
privatedouble price;
/** 客戶 */
private String customer;
/** 購入日期 */
private Date buyDay;
    /* getter he setter已經刪除 */
}

     input.xml文件內容如下:

     處理結果如下(output.xml):

     下次,將和大家一起討論關於Spring Batch 對固定長內容文件的讀寫問題。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章