此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Batch 文档 5.1.2! |
此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Batch 文档 5.1.2! |
Spring Batch 为读取 XML 记录和 将它们映射到 Java 对象以及将 Java 对象写入 XML 记录。
对流式处理 XML 的约束
StAX API 用于 I/O,因为其他标准 XML 解析 API 不适合批处理 处理要求(DOM 一次将整个输入加载到内存中,并且 SAX 控制 解析过程,允许用户仅提供回调)。 |
我们需要考虑 XML 输入和输出在 Spring Batch 中是如何工作的。首先,有一个
一些与文件读取和写入不同但在 Spring Batch 中通用的概念
XML 处理。使用 XML 处理,而不是需要的记录行(实例)
要进行标记化,则假定 XML 资源是“片段”的集合
对应于单个记录,如下图所示:FieldSet
在上述场景中,'trade' 标签被定义为 'root element'。万事 在 '<trade>' 和 '</trade>' 之间被视为一个 “片段”。Spring Batch 使用 Object/XML Mapping (OXM) 将片段绑定到对象。但是,Spring Batch 不是 与任何特定的 XML 绑定技术相关联。典型的用途是委托给 Spring OXM,它 为最流行的 OXM 技术提供统一的抽象。对 Spring OXM 是可选的,您可以选择实现特定于 Spring Batch 的接口 如果需要。与 OXM 支持的技术的关系显示在 下图:
通过介绍 OXM 以及如何使用 XML 片段来表示记录,我们 现在可以更仔细地检查读者和作者。
对流式处理 XML 的约束
StAX API 用于 I/O,因为其他标准 XML 解析 API 不适合批处理 处理要求(DOM 一次将整个输入加载到内存中,并且 SAX 控制 解析过程,允许用户仅提供回调)。 |
StaxEventItemReader
该配置为处理
记录。首先,考虑以下一组 XML 记录,这些记录
该 CAN 流程:StaxEventItemReader
StaxEventItemReader
<?xml version="1.0" encoding="UTF-8"?>
<records>
<trade xmlns="https://springframework.org/batch/sample/io/oxm/domain">
<isin>XYZ0001</isin>
<quantity>5</quantity>
<price>11.39</price>
<customer>Customer1</customer>
</trade>
<trade xmlns="https://springframework.org/batch/sample/io/oxm/domain">
<isin>XYZ0002</isin>
<quantity>2</quantity>
<price>72.99</price>
<customer>Customer2c</customer>
</trade>
<trade xmlns="https://springframework.org/batch/sample/io/oxm/domain">
<isin>XYZ0003</isin>
<quantity>9</quantity>
<price>99.99</price>
<customer>Customer3</customer>
</trade>
</records>
为了能够处理 XML 记录,需要满足以下条件:
-
根元素名称:构成 对象。示例配置通过 trade 的值演示了这一点。
-
Resource:表示要读取的文件的 Spring Resource。
-
Unmarshaller
:Spring OXM 提供的解组工具,用于映射 XML fragment 复制到对象。
-
Java
-
XML
以下示例演示如何定义与根一起使用的
元素 、 的资源 和 解组器
在 Java 中调用:StaxEventItemReader
trade
data/iosample/input/input.xml
tradeMarshaller
@Bean
public StaxEventItemReader itemReader() {
return new StaxEventItemReaderBuilder<Trade>()
.name("itemReader")
.resource(new FileSystemResource("org/springframework/batch/item/xml/domain/trades.xml"))
.addFragmentRootElements("trade")
.unmarshaller(tradeMarshaller())
.build();
}
以下示例演示如何定义与根一起使用的
元素 、 的资源 和 解组器
在 XML 中调用:StaxEventItemReader
trade
data/iosample/input/input.xml
tradeMarshaller
<bean id="itemReader" class="org.springframework.batch.item.xml.StaxEventItemReader">
<property name="fragmentRootElementName" value="trade" />
<property name="resource" value="org/springframework/batch/item/xml/domain/trades.xml" />
<property name="unmarshaller" ref="tradeMarshaller" />
</bean>
请注意,在此示例中,我们选择使用 ,它接受
作为 Map 传入的别名,第一个键和值是 fragment 的名称
(即根元素)和要绑定的对象类型。然后,类似于 a ,
映射到 Object Type 中字段的其他元素的名称描述为
map 中的键/值对。在配置文件中,我们可以使用 Spring 配置
实用程序来描述所需的别名。XStreamMarshaller
FieldSet
-
Java
-
XML
以下示例演示如何在 Java 中描述别名:
@Bean
public XStreamMarshaller tradeMarshaller() {
Map<String, Class> aliases = new HashMap<>();
aliases.put("trade", Trade.class);
aliases.put("price", BigDecimal.class);
aliases.put("isin", String.class);
aliases.put("customer", String.class);
aliases.put("quantity", Long.class);
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setAliases(aliases);
return marshaller;
}
以下示例演示如何在 XML 中描述别名:
<bean id="tradeMarshaller"
class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<util:map id="aliases">
<entry key="trade"
value="org.springframework.batch.samples.domain.trade.Trade" />
<entry key="price" value="java.math.BigDecimal" />
<entry key="isin" value="java.lang.String" />
<entry key="customer" value="java.lang.String" />
<entry key="quantity" value="java.lang.Long" />
</util:map>
</property>
</bean>
在输入时,读取器会读取 XML 资源,直到它识别出一个新的片段是
即将开始。默认情况下,读取器会匹配元素名称,以识别新的
fragment 即将启动。Reader 从
片段并将文档传递给反序列化器(通常是 Spring 周围的包装器
OXM ) 将 XML 映射到 Java 对象。Unmarshaller
总之,此过程类似于以下 Java 代码,它使用 injection 提供的 Spring 配置:
StaxEventItemReader<Trade> xmlStaxEventItemReader = new StaxEventItemReader<>();
Resource resource = new ByteArrayResource(xmlResource.getBytes());
Map aliases = new HashMap();
aliases.put("trade","org.springframework.batch.samples.domain.trade.Trade");
aliases.put("price","java.math.BigDecimal");
aliases.put("customer","java.lang.String");
aliases.put("isin","java.lang.String");
aliases.put("quantity","java.lang.Long");
XStreamMarshaller unmarshaller = new XStreamMarshaller();
unmarshaller.setAliases(aliases);
xmlStaxEventItemReader.setUnmarshaller(unmarshaller);
xmlStaxEventItemReader.setResource(resource);
xmlStaxEventItemReader.setFragmentRootElementName("trade");
xmlStaxEventItemReader.open(new ExecutionContext());
boolean hasNext = true;
Trade trade = null;
while (hasNext) {
trade = xmlStaxEventItemReader.read();
if (trade == null) {
hasNext = false;
}
else {
System.out.println(trade);
}
}
StaxEventItemWriter
Output 与 input 对称工作。需要一个 、 一个
marshaller 和 .将 Java 对象传递给编组处理程序(通常为
标准 Spring OXM Marshaller),它使用自定义事件写入
编写器,用于过滤为每个
fragment 的 fragment 中。StaxEventItemWriter
Resource
rootTagName
Resource
StartDocument
EndDocument
-
Java
-
XML
下面的 Java 示例使用 :MarshallingEventWriterSerializer
@Bean
public StaxEventItemWriter itemWriter(Resource outputResource) {
return new StaxEventItemWriterBuilder<Trade>()
.name("tradesWriter")
.marshaller(tradeMarshaller())
.resource(outputResource)
.rootTagName("trade")
.overwriteOutput(true)
.build();
}
下面的 XML 示例使用 :MarshallingEventWriterSerializer
<bean id="itemWriter" class="org.springframework.batch.item.xml.StaxEventItemWriter">
<property name="resource" ref="outputResource" />
<property name="marshaller" ref="tradeMarshaller" />
<property name="rootTagName" value="trade" />
<property name="overwriteOutput" value="true" />
</bean>
前面的配置设置了三个必需的属性并设置了可选的 attrbute,本章前面提到了,用于指定
可以覆盖现有文件。overwriteOutput=true
-
Java
-
XML
下面的 Java 示例使用与读取示例中使用的相同的编组处理程序 在本章前面显示:
@Bean
public XStreamMarshaller customerCreditMarshaller() {
XStreamMarshaller marshaller = new XStreamMarshaller();
Map<String, Class> aliases = new HashMap<>();
aliases.put("trade", Trade.class);
aliases.put("price", BigDecimal.class);
aliases.put("isin", String.class);
aliases.put("customer", String.class);
aliases.put("quantity", Long.class);
marshaller.setAliases(aliases);
return marshaller;
}
下面的 XML 示例使用与读取示例中使用的相同的封送处理程序 在本章前面显示:
<bean id="customerCreditMarshaller"
class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<util:map id="aliases">
<entry key="customer"
value="org.springframework.batch.samples.domain.trade.Trade" />
<entry key="price" value="java.math.BigDecimal" />
<entry key="isin" value="java.lang.String" />
<entry key="customer" value="java.lang.String" />
<entry key="quantity" value="java.lang.Long" />
</util:map>
</property>
</bean>
为了用 Java 示例进行总结,下面的代码说明了所有要点 讨论,演示了所需属性的编程设置:
FileSystemResource resource = new FileSystemResource("data/outputFile.xml")
Map aliases = new HashMap();
aliases.put("trade","org.springframework.batch.samples.domain.trade.Trade");
aliases.put("price","java.math.BigDecimal");
aliases.put("customer","java.lang.String");
aliases.put("isin","java.lang.String");
aliases.put("quantity","java.lang.Long");
Marshaller marshaller = new XStreamMarshaller();
marshaller.setAliases(aliases);
StaxEventItemWriter staxItemWriter =
new StaxEventItemWriterBuilder<Trade>()
.name("tradesWriter")
.marshaller(marshaller)
.resource(resource)
.rootTagName("trade")
.overwriteOutput(true)
.build();
staxItemWriter.afterPropertiesSet();
ExecutionContext executionContext = new ExecutionContext();
staxItemWriter.open(executionContext);
Trade trade = new Trade();
trade.setPrice(11.39);
trade.setIsin("XYZ0001");
trade.setQuantity(5L);
trade.setCustomer("Customer1");
staxItemWriter.write(trade);