我们在应用程序中使用spring-ws 2.2来使用Web服务。我们很高兴这样做了很长一段时间,一切都运行良好,除了现在我需要访问响应中的SOAP标头,我只是找不到这样做的方法。
我们正在使用配置了Jaxb2Marshaller的WebServiceTemplate(来自springs-ws)。 jaxb文件是使用xjc从wsdl生成的。我的回复中的标题元素如下所示:
<soapenv:Header>
<v1:ResponseHeader status="OK">
<v1:description>test</v1:description>
</v1:ResponseHeader>
</soapenv:Header>
在我的java类中,解析响应的代码看起来像这样(我删除了一些不相关的代码):
public CalculationData getValues(Integer id) throws IntegrationException {
WebServiceMessageCallback callback = createCallback(soapAction);
GetValuesRequest request = toGetValues(id);
GetValuesResponse response = null;
try {
response = (GetValuesResponse) webServiceTemplate.marshalSendAndReceive(request, callback);
} catch (SOAPFaultException fault) {
log.error("Soap fault occurred during getValues " + id);
throw new IntegrationException(fault);
}
CalculationData data = fromGetValues(response);
return data;
}
请帮我找到一个解决方案,用于从响应中的SOAP标头中提取信息。我必须能够解析作为属性发送的状态代码。
顺便说一下。我还有一个ResponseHeader.java jaxb类,它是从模式生成的。从最终更改中更新:
这是在内联ClientInterceptor实现后我的handleResponse方法的样子:
@Override
public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {
SoapMessage message = (SoapMessage) messageContext.getResponse();
Iterator<SoapHeaderElement> responseHeaderElements =
message.getSoapHeader().examineAllHeaderElements();
SoapHeaderElement header = null;
if (responseHeaderElements.hasNext()) {
header = responseHeaderElements.next();
} else {
log.error("Error! No ResponseHeader found in response.");
return false;
}
String responseCode = header.getAttributeValue(new QName(STATUS_QNAME));
responseMsg.put(RESPONSE_MSG_KEY, responseCode);
return true;
}
我尝试通过QName获取ResponseHeader元素,但由于某种原因,这似乎不起作用。但是,我只希望无论如何都能在soap标题中获得一个元素,这样可以正常工作。
答案 0 :(得分:1)
实现ClientInterceptor
,具体请参见handleResponse()方法。
要访问Soap Headers,请转换为SoapMessage
public final boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
QName v1ResponseHeaderQName = null;//todo
QName statusAttrQName = null;//todo
SoapMessage message = (SoapMessage) messageContext.getResponse();
Iterator<SoapHeaderElement> matchingHeaders = message.getSoapHeader().examineHeaderElements(v1ResponseHeaderQName);
String status = matchingHeaders.next().getAttributeValue(statusAttrQName);
}
然后致电webServiceTemplate.setInterceptors(..)
有关此内容的更多示例,请参阅AbstractWsSecurityInterceptor
及其子类。但请注意,这些拦截器涉及替换请求消息,您只想阅读响应消息。
问题是你现在正在处理原始肥皂消息,所以你已经失去了良好的弹簧编组,需要开始处理命名空间(QNames)和w3c Dom的东西。
为了让拦截器将头传递回调用代码,可以使拦截器成为在getValues(...)方法中设置的匿名内部类。
final Map<String,String> headers = new HashMap<>();
template.setInterceptors(new ClientInterceptor[]{new ClientInterceptor() {
@Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
return true;
}
@Override
public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {
headers.put("foo", "bar");
return false;
}
@Override
public boolean handleFault(MessageContext messageContext) throws WebServiceClientException {
return true;
}
@Override
public void afterCompletion(MessageContext messageContext, Exception ex) throws WebServiceClientException {
}
}});
template.marshalSendAndReceive(....);
答案 1 :(得分:1)
对于此用例,最佳解决方案是使用自定义WebServiceMessageExtractor
,如下所述:
http://veithen.github.io/2015/01/03/spring-ws-extracting-soap-headers-from-responses.html