如何解析带命名空间的Feign XML响应并获取属性值?
解析Feign返回的带命名空间XML并提取属性值的方案
一、优先用现成解码器结合注解处理
Feign自带的Jackson XML解码器(JacksonXmlDecoder)或JAXB解码器(JaxbDecoder)都能处理带命名空间的XML,无需完全自定义解码器,只需配合注解配置实体类即可。
1. Jackson XML解码器示例
先定义对应XML的实体类,通过注解绑定命名空间和属性:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; @JacksonXmlRootElement(namespace = "你的XML命名空间值", localName = "header") public class HeaderResponse { @JacksonXmlProperty(isAttribute = true, localName = "id") private String id; @JacksonXmlProperty(isAttribute = true, localName = "dateResponse") private String dateResponse; @JacksonXmlProperty(isAttribute = true, localName = "status") private String status; // getter、setter方法 public String getId() { return id; } public void setId(String id) { this.id = id; } }
接着在Feign配置类中指定使用该解码器:
import feign.codec.Decoder; import org.springframework.cloud.openfeign.support.JacksonXmlDecoder; import org.springframework.context.annotation.Bean; public class FeignConfig { @Bean public Decoder feignDecoder() { return new JacksonXmlDecoder(); } }
调用Feign接口后,直接从返回的HeaderResponse对象中获取id值即可。
2. JAXB解码器示例
若使用JAXB,给实体类添加JAXB注解:
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlAttribute; @XmlRootElement(namespace = "你的XML命名空间值", name = "header") public class HeaderResponse { @XmlAttribute(name = "id") private String id; // 其他属性及getter、setter方法 public String getId() { return id; } public void setId(String id) { this.id = id; } }
配置JAXB解码器:
import feign.codec.Decoder; import org.springframework.cloud.openfeign.support.JaxbDecoder; import org.springframework.context.annotation.Bean; public class FeignConfig { @Bean public Decoder feignDecoder() { return new JaxbDecoder(); } }
二、自定义解码器的适用场景
如果仅需提取单个属性(比如只拿id),且不想定义完整实体类,可使用XPath编写轻量自定义解码器:
import feign.Response; import feign.codec.Decoder; import org.w3c.dom.Document; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathFactory; import java.io.InputStream; import java.util.Iterator; import javax.xml.namespace.NamespaceContext; public class CustomHeaderIdDecoder implements Decoder { @Override public Object decode(Response response, java.lang.reflect.Type type) throws IOException { try (InputStream inputStream = response.body().asInputStream()) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); // 必须开启命名空间支持 DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(inputStream); XPath xpath = XPathFactory.newInstance().newXPath(); // 设置命名空间上下文 xpath.setNamespaceContext(new NamespaceContext() { @Override public String getNamespaceURI(String prefix) { if ("ns".equals(prefix)) { return "你的XML命名空间值"; } return null; } @Override public String getPrefix(String namespaceURI) { return null; } @Override public Iterator<?> getPrefixes(String namespaceURI) { return null; } }); // 提取id属性 String id = xpath.evaluate("//ns:header/@id", doc); return id; } catch (Exception e) { throw new IOException("XML解析失败", e); } } }
将该自定义解码器配置到Feign客户端即可使用。
总结
- 优先选择现成的Jackson XML或JAXB解码器,配合实体类注解实现解析,代码更规范易维护。
- 仅需单个属性且无需完整实体类时,再考虑用XPath编写自定义解码器。
内容的提问来源于stack exchange,提问作者aratata
相关产品推荐
相关产品推荐

