本篇博客源于工作中需要对XML字符串进行解析,总结出了两种主流实现方案。

具体内容请移步:跳转Github

下文对仓库代码关键代码进行了简单截取,可照抄工具类方法。

一、JAXB

1.1 依赖(jdk9+需要)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 在Java 9及以上版本中,JAXB API默认不再包含在Java SE中,需要手动添加依赖 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.1</version>
</dependency>

1.1 Vo类(注解)

此处指定好XML标签与VO类属性名的映射关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Getter
@XmlRootElement(name = "ENTITY")
public class UserVo {
private Long id;
private String name;
private String email;
private Integer age;

@XmlElement(name = "ID")
public void setId(Long id) {
this.id = id;
}
// ...

1.2 解析类(工具方法)

JAXB工具比较简单,不用配置,直接使用即可,推荐jdk8及以下的环境使用。

但是如果涉及到大型XML字符串或者需要频繁解析1,JAXB解析器可能会造成系统性能问题,遇到这种场景推荐使用第二种工具JsonXML。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;

/**
* XML 解析工具类
* 使用 JAXB 实现 XML 到 Java 对象的转换
*/
public class JAXBXmlParser {

/**
* 将 XML 字符串解析为指定类型的对象
*
* @param xmlStr XML 字符串
* @param clazz 目标类的 Class 对象
* @param <T> 目标类型
* @return 解析后的对象
* @throws JAXBException 当解析失败时抛出
*/
public static <T> T parseXmlToObject(String xmlStr, Class<T> clazz) throws JAXBException {

JAXBContext context = JAXBContext.newInstance(clazz);
Unmarshaller unmarshaller = context.createUnmarshaller();
StringReader reader = new StringReader(xmlStr);
return clazz.cast(unmarshaller.unmarshal(reader));
}
}

二、JsonXML

2.1 依赖

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Spring Boot 通常已经包含 Jackson Core 和 Databind -->
<!-- 添加 XML 支持 -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<!-- 可选:JAXB注解支持 -->
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.14.2</version>
</dependency>

2.2 Vo类(注解)

不需要写在Get方法上,直接写在属性名上即可,依然需要指定好对应关系。

1
2
3
4
5
6
7
8
@Data
@JacksonXmlRootElement(localName = "ENTITY")
public class UserVo {

@JacksonXmlProperty(localName = "ID")
private Long id;

// ...

2.1 解析类(配置以及工具方法)

JsonXML的配置项比较多,可以在初始化对象的时候指定配置,也可以用配置类(全局)。

具体的配置内容可以在我的Git仓库查看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
* 使用 Jackson XML 模块实现的 XML 解析工具类
* 与 Spring Boot 项目有更好的兼容性
*/
public class JacksonXmlParser {

private static final Logger logger = LoggerFactory.getLogger(JacksonXmlParser.class);

/**
* -- GETTER --
* 获取配置好的 XmlMapper 实例
* 可用于更高级的自定义操作
*/
@Getter
private static final XmlMapper xmlMapper;

static {
xmlMapper = new XmlMapper();

// 配置 XmlMapper
// 忽略未知属性,避免解析时因XML中有未知字段而报错
xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

// 注册 JAXB 注解模块(如果需要支持 JAXB 注解)
xmlMapper.registerModule(new JaxbAnnotationModule());

// 可以添加其他自定义配置
}

/**
* 将 XML 字符串解析为指定类型的对象
*
* @param xmlStr XML 字符串
* @param clazz 目标类的 Class 对象
* @param <T> 目标类型
* @return 解析后的对象
* @throws RuntimeException 当解析失败时抛出
*/
public static <T> T parseXmlToObject(String xmlStr, Class<T> clazz) {
try {
return xmlMapper.readValue(xmlStr, clazz);
} catch (IOException e) {
String errorMsg = String.format("XML解析失败: %s, XML内容: %s", e.getMessage(),
xmlStr.length() > 200 ? xmlStr.substring(0, 200) + "..." : xmlStr);
logger.error(errorMsg, e);
throw new RuntimeException(errorMsg, e);
}
}

/**
* 安全版本的解析方法,不会抛出异常
*
* @param xmlStr XML 字符串
* @param clazz 目标类的 Class 对象
* @param <T> 目标类型
* @return 解析后的对象,解析失败时返回null
*/
public static <T> T parseXmlToObjectSafely(String xmlStr, Class<T> clazz) {
try {
return parseXmlToObject(xmlStr, clazz);
} catch (RuntimeException e) {
logger.warn("XML解析失败,返回null: {}", e.getMessage());
return null;
}
}
}

三、两种方式简单对比

3.1 兼容性对比

JAXB 兼容性

  • ✅ JDK8及以下:内置支持,无需额外依赖
  • ⚠️ JDK9-16:需要单独添加依赖,API包名从javax.xml.bind变为jakarta.xml.bind
  • ✅ JDK17+:需要添加依赖,但API稳定
  • ✅ 与老系统兼容性极佳,是企业级标准

Jackson XML 兼容性

  • ✅ 全版本JDK兼容,统一依赖
  • ✅ 与Spring生态完美集成
  • ✅ 支持多种数据格式(JSON/XML/YAML/CSV等)
  • ⚠️ 需要学习新的注解体系(但可选支持JAXB注解)

兼容性结论

  • JAXB 在JDK版本变迁中有断档,需要处理包名变化
  • Jackson XML 提供更一致的跨版本体验

3.2 性能对比

根据多项基准测试,性能对比大致如下:

操作 JAXB Jackson XML 优势方
小型XML解析 中等 Jackson
大型XML解析 Jackson
对象序列化 中等 Jackson
内存使用 Jackson
启动时间 Jackson

性能结论

  • Jackson XML 在大多数场景下性能优于 JAXB
  • 特别在处理大型XML文档时,Jackson的优势更明显
  • JAXB 的启动时间较长(需要初始化上下文)