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

发布于 2024-12-05 18:59:01 字数 1057 浏览 6 评论 0原文

使用 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);
    }
}

Using a CXF Interceptor I'd like to append some Node to the xml being sent out to the server. I've created a interceptor (see below) that picks up the message as DOM Node, modifies it and writes it back to the message object.

Unfortunately the code does not work as expected - the XML sent to the server does not contain the 'magicWord'. IMHO I'm using the wrong phase for this.

So the question is: how can I modify an outgoing webservice request using the org.w3c.dom.Node syntax?

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

日裸衫吸 2024-12-12 18:59:01

最后我自己发现了如何做到这一点。

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

Finally I've found out myself how to do this.

  • the interceptor must use 'Phase.PRE_PROTOCOL'
  • the interceptor must use addAfter(SaajOutInterceptor) - SaajOutInterceptor provides the Node in the Message
  • interceptor class should derive from AbstractSoapInterceptor
  • interceptor's handleMessage does not do the dirty work of modifying the DOM itself, rather it adds a new interceptor to the message using message.getInterceptorChain().add(...).
  • the freshly added interceptor is then supposed to modify the DOM
小帐篷 2024-12-12 18:59:01

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

If you want to modify the body of a request using the DOM api in a cxf interceptor the correct Phase is USER_PROTOCOL

The SAAJOutInterceptor creates the DOM structure, so your interceptor must be run after that, this means that you might have to add it to the interceptors chain since it is not always added by cxf for performance reasons.

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);
}

to add the interceptors:

import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
import org.apache.cxf.endpoint.Client;

/*[...]*/
client.getOutInterceptors().add(new SAAJOutInterceptor())
client.getOutInterceptors().add(new MySoapNodeModifierInterceptor())
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文