代码之家  ›  专栏  ›  技术社区  ›  Dave

SpringSOAP拦截器如何修改消息的内容?

  •  5
  • Dave  · 技术社区  · 14 年前

    我正在尝试为Web服务编写一个拦截器,该拦截器将在发送到端点之前修改SOAP消息的内容。如果客户机发送了一条消息,其中某个元素的值为1,我希望能够将该元素更改为2,以便当消息到达端点时,看起来客户机提交的是2而不是1。我不确定这是一项让我苦恼的艰巨任务,还是一项让我做得比实际需要更困难的简单任务。

    我已经完成了一些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;
    }
    

    我希望有一个机会,soembody else已经解决了这个特定的问题。任何见解都会受到赞赏。谢谢。

    3 回复  |  直到 8 年前
        1
  •  6
  •   skaffman    14 年前

    修改有效载荷有点棘手。我找到的唯一方法是使用 getPayloadSource() getPayloadResult() 方法对 SoapBody 暴露 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());
    

    我希望看到一种更好的方法。

        2
  •  1
  •   Dave    14 年前

    我意识到在以后的某个时候修改请求会更容易一些。我不需要修改原始的SOAP消息,只要我能够在数据到达我的端点之前修改它。

    我使用的端点都是extendabstractdom4jpayloadEndpoint,所以我将这些端点包装在一个代理中,该代理允许我在继续我的端点之前修改请求元素。即。:

    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 );
        }
    
        3
  •  1
  •   K St. Clair    8 年前

    我修改了此答案中的代码以插入 <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插入SOAP主体之前激活了SaajSoapMessageFactory。