在 Spring Batch 4 中,StaxEventItemWriter 是一个用于将数据项写入 XML 文件的 ItemWriter 实现,它基于 STAX(Streaming API for XML)技术,适合处理大型 XML 文件,具有内存效率高的特点。
StaxEventItemWriter 类的核心特性:
流式 XML 处理:基于 STAX 的 XMLStreamWriter 进行写入,不会将整个 XML 文档加载到内存,而是逐元素生成,适合处理大数据量场景,避免内存溢出。
灵活的 XML 结构配置:可自定义根元素、记录元素(每个数据项对应的 XML 标签)等结构,支持自定义编码和 XML 格式。例如:
StaxEventItemWriter<User> writer = new StaxEventItemWriter<>();
try {
XStreamMarshaller marshaller = new XStreamMarshaller();
Map<String, Class> aliases = new HashMap<>();
aliases.put("my-user", User.class);
marshaller.setAliases(aliases);
// 5.2 启用格式化输出(需XStream配置)
XStream xstream = marshaller.getXStream();
xstream.autodetectAnnotations(true);
xstream.setMode(XStream.NO_REFERENCES);
writer.setMarshaller(marshaller);
writer.setRootTagName("users"); // 自定义根元素名
writer.setEncoding("GBK"); // 配置XML编码(默认UTF-8),支持中文编码
writer.setResource(new FileSystemResource("f://users.xml")); // 设置文件路径
writer.afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}对象 → XML 转换:依赖 Marshaller(如 JAXB、XStream 等)将 Java 对象转换为 XML 元素,无需手动拼接 XML 字符串。
事务支持:遵循 Spring Batch 的事务管理机制,确保在批处理过程中出现异常时,能正确回滚未完成的写入操作。
该示例将从 resource 目录下名为 users.csv 文件读取数据,然后使用 StaxEventItemWriter 类将数据写入到 F:\users.xml 文件。
由于我们需要使用 XStreamMarshaller 序列化器,因此需要引入 spring-oxm 和 xstream 依赖,如下:
<!-- 从XML读取数据,StaxEventItemReader 需要依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> </dependency> <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.7</version> </dependency>
其中:
spring-oxm 定义了 Marshaller(对象 → XML)和 Unmarshaller(XML → 对象)标准接口,屏蔽底层实现差异(如 JAXB、XStream 等)。
xstream 提供高效的序列化/反序列化实现,无需 XML Schema 或注解配置。支持自定义字段别名、集合映射,轻量级且性能较好。
在项目的 resources 目录下面创建名为 users.csv 的文件,内容如下:
"id","username","password" 1,张三,"13BC03AC29FAC7B29736EC3BE5C2F55A" 2,李四,"5E5994FBCFA922D804DF45295AE98604" 3,王五,"6C14DA109E294D1E8155BE8AA4B1CE8E" 4,赵六,"03774AD7979A5909E78F9C9DB3A2F0B2"
创建一个简单的 POJO 用于映射 csv 读取的每一行数据,如下:
package com.hxstrive.spring_batch.staxItemWriterDemo.dto;
import lombok.Data;
import lombok.ToString;
/**
* 用户DTO
* @author hxstrive.com
*/
@Data
@ToString
public class User {
private int id;
private String username;
private String password;
}使用 @Configuration 注解创建配置类,配置 Spring Batch 的 Job、Step、ItemReader 和 ItemWriter,代码如下:
package com.hxstrive.spring_batch.staxItemWriterDemo.config;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hxstrive.spring_batch.staxItemWriterDemo.dto.User;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.batch.item.file.transform.LineAggregator;
import org.springframework.batch.item.xml.StaxEventItemWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.oxm.xstream.XStreamMarshaller;
import org.springframework.validation.BindException;
import java.util.HashMap;
import java.util.Map;
/**
* Spring Batch 配置类
* @author hxstrive.com
*/
@Configuration
public class BatchConfig {
// 用于创建和配置 Job 对象的工厂类
@Autowired
private JobBuilderFactory jobBuilderFactory;
// 用于创建和配置 Step 对象的工厂类
@Autowired
private StepBuilderFactory stepBuilderFactory;
// 创建Job对象
@Bean
public Job staxEventItemWriterDemoJob() {
return jobBuilderFactory.get("staxEventItemWriterDemoJob-" + System.currentTimeMillis())
.start(staxEventItemWriterDemoStep())
.build();
}
// 创建Step对象
@Bean
public Step staxEventItemWriterDemoStep() {
return stepBuilderFactory.get("staxEventItemWriterDemoStep")
.<User, User>chunk(2)
.reader(flatFileItemReader())
.writer(xmlItemWriter())
.build();
}
// 创建ItemReader对象
@Bean
@StepScope //将 Bean 的生命周期与 Step 执行上下文 绑定
public FlatFileItemReader<? extends User> flatFileItemReader() {
FlatFileItemReader<User> reader = new FlatFileItemReader<>();
reader.setResource(new ClassPathResource("users.csv"));
reader.setLinesToSkip(1); // 跳过文件第一行,因为第一行是字段名
// 解析数据
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
tokenizer.setNames("id", "username", "password");
// 把解析出的数据映射到 User 对象中
DefaultLineMapper<User> lineMapper = new DefaultLineMapper<>();
lineMapper.setLineTokenizer(tokenizer);
lineMapper.setFieldSetMapper(new FieldSetMapper<User>(){
@Override
public User mapFieldSet(FieldSet fieldSet) throws BindException {
// 将读取的每行数据,转换成一个个 User 对象
User user = new User();
user.setId(fieldSet.readInt("id"));
user.setUsername(fieldSet.readString("username"));
user.setPassword(fieldSet.readString("password"));
System.out.println("reading user: " + user);
return user;
}
});
lineMapper.afterPropertiesSet();
reader.setLineMapper(lineMapper);
return reader;
}
// 创建ItemWriter对象【关键方法】
@Bean
public StaxEventItemWriter<? super User> xmlItemWriter() {
System.out.println("xmlItemWriter()");
StaxEventItemWriter<User> writer = new StaxEventItemWriter<>();
try {
XStreamMarshaller marshaller = new XStreamMarshaller();
Map<String, Class> aliases = new HashMap<>();
aliases.put("user", User.class);
marshaller.setAliases(aliases);
writer.setMarshaller(marshaller);
writer.setRootTagName("users");
writer.setResource(new FileSystemResource("f://users.xml"));
writer.afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}
return writer;
}
}上述配置,我们重点查看 xmlItemWriter() 方法,该方法创建并配置了一个 StaxEventItemWriter,用于将数据以 XML 格式写入文件。代码详细说明:
(1)方法定义,返回一个 StaxEventItemWriter 实例,泛型指定为 ? super User,表示它可以处理 User 类型及其父类的对象。
public StaxEventItemWriter<? super User> xmlItemWriter()
(2)实例化 StaxEventItemWriter,并指定处理 User 类型的对象。
StaxEventItemWriter<User> writer = new StaxEventItemWriter<>();
(3)使用 XStream 库进行对象到 XML 的转换(XStream 是一个简单的 XML 序列化工具)。通过别名映射,将 User 类在 XML 中显示为 <user> 标签(而非全类名),如下:
// 配置XML元素别名映射
// key: XML元素名, value: 对应的Java类
Map<String, Class> aliases = new HashMap<>();
aliases.put("user", User.class); // 将 <User> 对象映射为 <user> XML元素
marshaller.setAliases(aliases);(4)配置写入器核心参数:
writer.setMarshaller(marshaller); // 设置XML序列化器
writer.setRootTagName("users"); // 设置XML根标签名为<users>
writer.setResource( // 设置输出文件路径
new FileSystemResource("f://users.xml") // 写入F盘users.xml文件
);
// 初始化检查(Spring生命周期回调)
writer.afterPropertiesSet(); // 验证必要属性是否已设置老样子,仅在 Spring Boot 启动类上多添加 @EnableBatchProcessing 注解,开启批处理功能。代码如下:
package com.hxstrive.spring_batch.staxItemWriterDemo;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableBatchProcessing // 开启批处理
public class SpringBatchDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBatchDemoApplication.class, args);
}
}运行项目,输出日志如下图:

上图中,成功读取了四行数据。
再到 F 盘看看是否创建了 users.xml 文件,查看其内容,如下图:

到这里,你已经学会如何将数据写入到 XML 文件。
更多关于 StaxEventItemWriter 类的用法,请参考官方文档。