如何使用CXF拦截器和org.w3c.dom.Node修改web服务请求

4
使用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);
    }
}
2个回答

5

最终我自己找到了如何做到这一点。

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

2
嗨,斯特凡,你能分享一下你是如何做到这一点的代码吗?我正在尝试做更多或更少相同的事情。我必须修改DOM中SOAP头部分的值。 - Marco
我不确定这是否已经改变,但目前来看,USER_PROTOCOL似乎是这种拦截器的最佳阶段,您不需要添加一个拦截器来添加另一个拦截器,可以查看我的回复。 - molok

1
如果您想使用DOM API在cxf拦截器中修改请求体,则正确的阶段是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())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接