我有一个 PersonProxy,它包含一个调用第三方网络服务的方法。 AttachmentResponse 是一个 wsdl 生成的类 Decoder 被配置为将响应解码为 Wsdl 生成的类。我编写了一个 api,它调用 PersonProxy 类方法来获取响应。在解码器中解组时,在 AttachmentResponse 中 _return 为空。无法在 _return 变量中获取二进制数据。请帮助解决这个问题
@FeignClient(name = "PersonProxyWebService", url = "${url}",configuration = ServiceConfiguration.class)
public interface PersonProxy {
@GetMapping(value = "", consumes = MediaType.TEXT_XML_VALUE, produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE})
AttachmentResponse getResultAttachment(Long attachementId);
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "attachmentResponse", propOrder = {
"_return"
})
@XmlRootElement(name = "attachmentResponse")
public class AttachmentResponse {
@XmlElement(name = "return")
protected byte[] _return;
//getter and setter
}
public class SOAPDecoder implements Decoder {
@Override
public Object decode(Response response, Type type) throws IOException {
if (response.status() == 404)
return Util.emptyValueOf(type);
if (response.body() == null)
return null;
while (type instanceof ParameterizedType) {
ParameterizedType ptype = (ParameterizedType) type;
type = ptype.getRawType();
}
if (!(type instanceof Class)) {
throw new UnsupportedOperationException(
"SOAP only supports decoding raw types. Found " + type);
}
try (Scanner scanner = new Scanner(response.body().asInputStream())) {
Optional<String> soapEnvOpt= scanner.findAll(pattern).map(f->f.group(1)).findFirst();
if(soapEnvOpt.isPresent()) {
SOAPMessage message = MessageFactory.newInstance(soapProtocol).createMessage(null,new ByteArrayInputStream(soapEnvOpt.get().getBytes()));
if (message.getSOAPBody() != null) {
if (message.getSOAPBody().hasFault()) {
throw new SOAPFaultException(message.getSOAPBody().getFault());
}
Unmarshaller unmarshaller = jaxbContextFactory.createUnmarshaller((Class<?>) type);
if (this.useFirstChild) {
return unmarshaller.unmarshal(message.getSOAPBody().getFirstChild());
} else {
return unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument());
}
}
}
} catch (SOAPException | JAXBException e) {
throw new DecodeException(response.status(), e.toString(), response.request(), e);
} finally {
if (response.body() != null) {
response.body().close();
}
}
return Util.emptyValueOf(type);
}
}
在调试模式下,响应是这样的,但返回字段是>>>null in Wsdl generated class。
如何map contentId (cid) 在客户端提取二进制数据?
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:attachmentResponse>
xmlns:ns2="http://mscs.com/emr">
<return>
<xop:Include
xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:180aba29-24c2-44cd-b0a5-63a3b5ff4189-5@cxf.apache.org"/>
</return>
</ns2:attachmentResponse>
</soap:Body>
</soap:Envelope>
回答1
OpenFeign 中的默认 SOAPDecoder
无法正确处理 MTOM。为了使其工作,需要实施 2 个更改:
- 将
MimeHeaders
传播到SOAPMessage
,如 Github 问题 https://github.com/OpenFeign/feign/issues/1732 中所述 - 将
AttachmentUnmarshaller
添加到 JAXBUnmarshaller
,如此处所述 https://stackoverflow.com/questions/24407360/unmarshalling-xop-with-jaxb/24417032#24417032