Spring Soap拦截器如何修改消息的内容?
我试图编写一个Web服务的拦截器,它将在发送到端点之前修改Soap消息的内容。如果客户端发送的消息中的某个元素的值为1,我希望能够将该元素更改为2,以便当消息到达端点时,它看起来好像客户端提交了2而不是1.我不确定这是一项困难的任务,还是一件容易的事情,而我正在努力做到这一点。Spring Soap拦截器如何修改消息的内容?
我已经通过了一些Spring拦截器;但验证和日志记录拦截器并不是每个都会改变正在传输的消息。 Wss4jSecurityInterceptor确实为MessageContext添加了一些属性;但我还没有能够利用它正在做的任何事情。我有一个拦截器的外壳;但没有任何事情做任何有价值的事情。
public boolean handleRequest(MessageContext messageContext, Object endpoint)
throws Exception {
SaajSoapMessage saajSoapMessage = (SaajSoapMessage) messageContext
.getRequest();
SOAPMessage soapMessage = saajSoapMessage.getSaajMessage();
SOAPBody soapBody = soapMessage.getSOAPBody();
return true;
}
我当时希望有其他人已经解决了这个问题。任何洞察力将不胜感激。谢谢。
修改有效负载有点棘手。我发现完成这项工作的唯一方法是在SoapBody
上使用getPayloadSource()
和getPayloadResult()
方法,这些方法暴露javax.xml.transform
友好对象用于处理数据。
这是烦人的重量级,但你可以做这样的事情:
Transformer identityTransform = TransformerFactory.newInstance().newTransformer();
DOMResult domResult = new DOMResult();
identityTransform.transform(soapBody.getPayloadSource(), domResult);
Node bodyContent = domResult.getNode(); // modify this
identityTransform.transform(new DOMSource(bodyContent), soapBody.getPayloadResult());
我很乐意看到这样做的更好的方法。
我意识到在晚些时候改变请求很容易。我不需要修改原始SOAP消息,只要我能够在数据到达我的端点之前修改它。
我正在使用的端点都扩展了AbstractDom4jPayloadEndpoint - 所以我将这些端点包装在允许我在继续到端点之前修改请求元素的代理中。即:
public class MyProxyEndpoint extends AbstractDom4jPayloadEndpoint
@Override
protected Element invokeInternal(
Element requestElement,
Document responseDocument) throws Exception
{
if(requestElement != null)
{
// alter request element
}
return (Element) this.invokeMethod.invoke(
this.target,
requestElement,
responseDocument);
}
我修改了代码在此答案的<authentication/>
元素插入到所有的SOAP体的请求:
@Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
logger.trace("Enter handleMessage");
try {
SaajSoapMessage request = (SaajSoapMessage) messageContext.getRequest();
addAuthn(request);
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
return true;
}
protected void addAuthn(SaajSoapMessage request) throws TransformerException {
Transformer identityTransform = TransformerFactory.newInstance().newTransformer();
DOMResult domResult = new DOMResult();
identityTransform.transform(request.getPayloadSource(), domResult);
Node bodyContent = domResult.getNode();
Document doc = (Document) bodyContent;
doc.getFirstChild().appendChild(authNode(doc));
identityTransform.transform(new DOMSource(bodyContent), request.getPayloadResult());
}
protected Node authNode(Document doc) {
Element authentication = doc.createElementNS(ns, "authentication");
Element username = doc.createElementNS(ns, "username");
username.setTextContent(authn.getUsername());
Element password = doc.createElementNS(ns, "password");
password.setTextContent(authn.getPassword());
authentication.appendChild(username);
authentication.appendChild(password);
return authentication;
}
使用这种溶液,因为WebServiceMessageCallback要求我更改文档,并在由配置的Jaxb2Marshaller插入肥皂主体之前,SaajSoapMessageFactory被激活。
谢谢。你是对的 - 它不像人们希望的那样直截了当。我实际上以另一种方式解决了我的问题。虽然它没有直接解决我的原始问题 - 它解决了我目前的问题。 – Dave 2010-07-28 18:00:11