Spring Boot使用WebClient调用XML接口遇UnmarshalException问题求助
核心问题:XML命名空间不匹配
错误提示明确指出:接口返回的是带命名空间http://www.concursolutions.com/api/expense/extract/2010/02的<definitions>元素,但你的POJO类未配置对应命名空间,JAXB预期的是无命名空间的<definitions>,因此解析失败。
分步解决
1. 给POJO配置XML命名空间
你需要为Definitions和Definition类指定对应命名空间,有两种配置方式可选:
方式一:类级别单独配置
修改Definitions.java:
import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; import jakarta.xml.bind.annotation.XmlRootElement; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; @XmlRootElement(name = "definitions", namespace = "http://www.concursolutions.com/api/expense/extract/2010/02") @XmlAccessorType(XmlAccessType.FIELD) @Data @AllArgsConstructor @NoArgsConstructor public class Definitions { // 移除xmlns和i字段:这两个是XML命名空间声明属性,不属于业务数据,JAXB会自动处理 private List<Definition> definition; }
修改Definition.java:
import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlRootElement; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor @XmlRootElement(name = "definition", namespace = "http://www.concursolutions.com/api/expense/extract/2010/02") public class Definition { private String id; private String name; // XML元素<job-link>与Java字段joblink名称不匹配,需指定映射关系 @XmlElement(name = "job-link") private String joblink; }
方式二:包级别统一配置(推荐)
在模型类所在包下创建package-info.java文件,内容如下:
@XmlSchema( namespace = "http://www.concursolutions.com/api/expense/extract/2010/02", elementFormDefault = XmlNsForm.QUALIFIED ) package com.concur.models; import jakarta.xml.bind.annotation.XmlNsForm; import jakarta.xml.bind.annotation.XmlSchema;
该配置会让包下所有JAXB类默认使用指定命名空间,无需每个类单独添加namespace属性,更简洁易维护。
2. 处理字段与XML元素的映射问题
- XML中的
<job-link>元素与Java字段joblink名称不一致,必须用@XmlElement(name = "job-link")明确映射关系,否则JAXB无法匹配。 - 移除
Definitions类中的xmlns和i字段:这两个是XML的命名空间声明属性,不属于业务数据,JAXB会自动处理命名空间逻辑,保留反而会干扰解析。
3. 关于移除@XmlAccessorType后的错误
移除@XmlAccessorType(XmlAccessType.FIELD)后出现IllegalAnnotationsException,原因是:
JAXB默认访问类型为XmlAccessType.PROPERTY(通过getter/setter访问),而Lombok的@Data注解会为public字段自动生成getter/setter,导致JAXB同时识别到public字段和对应的getter/setter,产生访问冲突。保留@XmlAccessorType(XmlAccessType.FIELD)可让JAXB直接通过字段访问,避免该冲突,因此这个注解是必需的。
验证修改
完成上述修改后,原WebClient调用代码无需改动,重新测试即可正常将XML响应解析为Java POJO。
内容的提问来源于stack exchange,提问作者Ajinkya Mahagaonkar

