2010-07-08 106 views
5

我試圖編寫一個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; 
} 

我當時希望有其他人已經解決了這個問題。任何洞察力將不勝感激。謝謝。

回答

6

修改有效負載有點棘手。我發現完成這項工作的唯一方法是在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()); 

我很樂意看到這樣做的更好的方法。

+0

謝謝。你是對的 - 它不像人們希望的那樣直截了當。我實際上以另一種方式解決了我的問題。雖然它沒有直接解決我的原始問題 - 它解決了我目前的問題。 – Dave 2010-07-28 18:00:11

1

我意識到在晚些時候改變請求很容易。我不需要修改原始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); 
    } 
1

我修改了代碼在此答案的<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被激活。