【问题标题】:howto modify a webservice request using CXF interceptors with org.w3c.dom.Node如何使用带有 org.w3c.dom.Node 的 CXF 拦截器修改 Web 服务请求
【发布时间】:2011-11-21 14:23:29
【问题描述】:

使用 CXF 拦截器我想将一些节点附加到要发送到服务器的 xml 中。我创建了一个拦截器(见下文),它将消息作为 DOM 节点拾取,对其进行修改并将其写回消息对象。

不幸的是,代码没有按预期工作 - 发送到服务器的 XML 不包含“magicWord”。恕我直言,我为此使用了错误的阶段。

所以问题是:如何使用 org.w3c.dom.Node 语法修改传出 Web 服务请求?

package dummy;

import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

class DummyInterceptor extends AbstractPhaseInterceptor {

    String magicWord = "abc";

    public DummyInterceptor() {
        super(Phase.PRE_PROTOCOL);
    }

    public void handleMessage(Message message) {
        Document document = (Document) message.getContent(Node.class);
        NodeList nodes = document.getElementsByTagName("wsse:Security");
        if (nodes.getLength() == 1) {
            Node wsseSecurityNode = nodes.item(0);
            wsseSecurityNode.appendChild(document.createTextNode(magicWord));
        }
        message.setContent(Node.class, document);
    }
}

【问题讨论】:

    标签: web-services dom cxf interceptor


    【解决方案1】:

    我终于找到了自己的方法。

    • 拦截器必须使用“Phase.PRE_PROTOCOL”
    • 拦截器必须使用 addAfter(SaajOutInterceptor) - SaajOutInterceptor 提供消息中的节点
    • 拦截器类应该派生自 AbstractSoapInterceptor
    • 拦截器的 handleMessage 不做修改 DOM 本身的繁琐工作,而是使用 message.getInterceptorChain().add(...) 向消息添加一个新的拦截器。
    • 新添加的拦截器应该会修改 DOM

    【讨论】:

    • 嗨 stefan,你能分享一下你是如何做到这一点的代码吗?我正在尝试或多或少做同样的事情。我必须修改 DOM 的 soap 标头部分中的值。
    • 我不确定这是否已经改变,但到目前为止 USER_PROTOCOL 似乎是这种拦截器的最佳阶段,你不需要添加一个拦截器来添加另一个,看我的回复。
    【解决方案2】:

    如果你想在 cxf 拦截器中使用 DOM api 修改请求的主体,正确的 Phase 是 USER_PROTOCOL

    SAAJOutInterceptor 创建 DOM 结构,因此您的拦截器必须在此之后运行,这意味着您可能必须将其添加到拦截器链中,因为出于性能原因它并不总是由 cxf 添加。

    import org.apache.cxf.binding.soap.SoapMessage;
    import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
    import org.apache.cxf.interceptor.Fault;
    import org.apache.cxf.phase.Phase;
    import org.w3c.dom.Node;
    
    import javax.xml.soap.SOAPException;
    import javax.xml.soap.SOAPMessage;
    
    abstract public class SoapNodeModifierInterceptor extends AbstractSoapInterceptor {
        SoapNodeModifierInterceptor() { super(Phase.USER_PROTOCOL); }
    
        @Override public void handleMessage(SoapMessage message) throws Fault {
            try {
                if (message == null) {
                    return;
                }
                SOAPMessage sm = message.getContent(SOAPMessage.class);
                if (sm == null) {
                    throw new RuntimeException("You must add the SAAJOutInterceptor to the chain");
                }
    
                modifyNodes(sm.getSOAPBody());
    
            } catch (SOAPException e) {
                throw new RuntimeException(e);
            }
        }
    
        abstract void modifyNodes(Node node);
    }
    
    

    添加拦截器:

    import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
    import org.apache.cxf.endpoint.Client;
    
    /*[...]*/
    client.getOutInterceptors().add(new SAAJOutInterceptor())
    client.getOutInterceptors().add(new MySoapNodeModifierInterceptor())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 2016-10-08
      • 1970-01-01
      • 2023-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多