Spring Cloud Feign调用WebService无法提取含CID的二进制数据求助
解决方案:Feign调用WebService处理MTOM/XOP附件映射问题
问题根源是你的自定义SOAPDecoder未处理MTOM/XOP格式的附件解析,响应中xop:Include标签指向的cid对应MIME附件,但解码器没有将cid映射为实际二进制数据,导致_return字段为空。以下是具体解决步骤:
启用Feign客户端的MTOM支持
集成支持MTOM的SOAP消息工厂,比如Spring WS的SaajSoapMessageFactory,开启MTOM后才能解析MIME附件:@Bean public SaajSoapMessageFactory soapMessageFactory() { SaajSoapMessageFactory factory = new SaajSoapMessageFactory(); factory.setMtomEnabled(true); return factory; }将该工厂注入自定义SOAPDecoder,让解码器具备MTOM处理能力。
修改自定义SOAPDecoder,添加XOP附件解析逻辑
原解码器仅解析SOAP Body的XML结构,需补充cid到二进制数据的映射逻辑。示例代码(基于Spring WS):public class CustomMTOMSOAPDecoder extends SOAPDecoder { private final SaajSoapMessageFactory messageFactory; public CustomMTOMSOAPDecoder(SaajSoapMessageFactory messageFactory) { this.messageFactory = messageFactory; } @Override public Object decode(Response response, Type type) throws IOException, DecodeException { // 将响应流转换为SOAP消息 InputStream inputStream = response.body().asInputStream(); SoapMessage soapMessage = messageFactory.createWebServiceMessage(inputStream); // 定位所有xop:Include节点 Document document = soapMessage.getDocument(); XPath xpath = XPathFactory.newInstance().newXPath(); xpath.setNamespaceContext(new NamespaceContext() { @Override public String getNamespaceURI(String prefix) { return "xop".equals(prefix) ? "http://www.w3.org/2004/08/xop/include" : XMLConstants.NULL_NS_URI; } @Override public String getPrefix(String namespaceURI) { return null; } @Override public Iterator<?> getPrefixes(String namespaceURI) { return null; } }); NodeList includeNodes = (NodeList) xpath.evaluate("//xop:Include", document, XPathConstants.NODESET); for (int i = 0; i < includeNodes.getLength(); i++) { Element includeElement = (Element) includeNodes.item(i); String cid = includeElement.getAttribute("href").replace("cid:", ""); // 根据cid获取对应附件 Attachment attachment = soapMessage.getAttachment(cid); if (attachment != null) { byte[] binaryData = FileCopyUtils.copyToByteArray(attachment.getInputStream()); // 将二进制数据替换xop节点内容(若JAXB接受Base64则编码,否则直接处理字节数组) includeElement.setTextContent(Base64.getEncoder().encodeToString(binaryData)); } } // 反序列化修改后的XML为AttachmentResponse JAXBContext jaxbContext = JAXBContext.newInstance(AttachmentResponse.class); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); return unmarshaller.unmarshal(new DOMSource(document)); } }注意:需确保
AttachmentResponse的_return字段对应的JAXB注解正确(如@XmlElement(name = "return")),且类型支持二进制数据(如byte[])。配置Feign请求头,指定MTOM格式
在PersonProxy接口方法中添加请求头,告知服务端返回MTOM格式响应:@FeignClient(name = "personService", url = "${third-party.ws.url}", configuration = FeignMTOMConfig.class) public interface PersonProxy { @PostMapping(value = "/ws/person", consumes = "application/xop+xml", produces = "application/xop+xml") @Headers({ "Content-Type: application/xop+xml; charset=utf-8; type=\"text/xml\"", "Accept: application/xop+xml; charset=utf-8; type=\"text/xml\"" }) AttachmentResponse getAttachment(); }验证附件解析逻辑
调试时可打印soapMessage.getAttachments()确认cid对应的附件存在,同时检查JAXB生成类的字段映射是否正确,确保二进制数据能正确注入_return字段。
内容的提问来源于stack exchange,提问作者Rohit yadav
相关产品推荐
相关产品推荐

