本篇博客源于工作中需要对XML字符串进行解析,总结出了两种主流实现方案。
具体内容请移步:跳转Github
下文对仓库代码关键代码进行了简单截取,可照抄工具类方法。
一、JAXB
1.1 依赖(jdk9+需要)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <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;
public class JAXBXmlParser {
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
|
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
<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;
public class JacksonXmlParser {
private static final Logger logger = LoggerFactory.getLogger(JacksonXmlParser.class);
@Getter private static final XmlMapper xmlMapper;
static { xmlMapper = new XmlMapper();
xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
xmlMapper.registerModule(new JaxbAnnotationModule());
}
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); } }
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 的启动时间较长(需要初始化上下文)