使用spring ws在soap请求中发送XmlData

use*_*085 6 java soap spring-ws

我要求发XmlDataCDATA哪个返回一个附件的SOAP请求。

使用org.springframework.oxm.jaxb.Jaxb2Marshaller的编组与解组。

<![CDATA[<tag>Test</tag>]]> 这是我想在soap请求中发送的东西,远程服务希望它以相同的方式看到。

我已经创建了数据但是当我使用 webServiceTemplate.marshalSendAndReceive(payloadRequest, SoapActionCallback)

不知何故,有效载荷请求 xmltags 被编码并显示为

&lt;![CDATA[&lt;tag&gt;Test&lt;\tag&gt;

由于这种编码,远程服务无法处理请求并发送 org.springframework.ws.soap.client.SoapFaultClientException: Object reference not set to an instance of an object.

我该如何解决这个问题?有什么建议!

更新:spring mvc 的 defaultHtmlEscape 作为 web.xml 中的上下文参数是否负责这种行为?

Ale*_*ica 4

我今天在工作中遇到了同样的问题,当时我们必须在从银行 Web 服务公开的 WSDL 中定义的数据结构的字段文本上注入 CDATA 部分。

要求是引入 CDATA 部分以将 Unicode 字符“+”转义到电话号码字段中。不可能出于各种动机而更改 WSDL。

我们有相同的环境:

 org.springframework.oxm.jaxb.Jaxb2Marshaller

webServiceTemplate.marshalSendAndReceive(payloadRequest, SoapActionCallback)
Run Code Online (Sandbox Code Playgroud)

和相同的失败结果

&lt;![CDATA[&lt;tag&gt;+&lt;\tag&gt;
Run Code Online (Sandbox Code Playgroud)

代替

<[[CDATA[+]]>
Run Code Online (Sandbox Code Playgroud)

经过多次测试并在 Stackoverflow 和其他网站上咨询了许多字体后,我们了解到 JAXB 引擎本身并不支持该解决方案,因此有必要将 SOAP 消息操纵为处理请求的准时步骤。

其他解决方案表明使用第三方插件和库,例如 MOXy,以实现对 CDATA 部分以及 JAXB 的强大支持。但该解决方案不可能以 ASAP 的形式快速集成到大型企业应用程序中。

我在此回复中发布的解决方案允许使用经典 DOMSource 对象的规范方法从 messagecontext 转换消息 SOAP 来注入 CDATASection。

在您的答案中,您公开了解决方案的一部分,这是 marshalSendAndReceive 的回调。

如果您定义方法支持的临时回调marshalSendAndReceive,并在此回调中操纵注入 CDATASection 的 DOMSource,则可以解决该问题。

这是代码:

WebServiceMessageCallback callbackCDATANumTelefono = new WebServiceMessageCallback() {
           public void doWithMessage(WebServiceMessage message) {

                //Recover the DOMSource dal message soap
                DOMSource domSource = (DOMSource)message.getPayloadSource();

                //recover set of child nodes of domsource
                NodeList nodeList = domSource.getNode().getChildNodes();

                //definisco il nome del tag da cercare
                String nameNumTel = "ns2:sNumTel"; //in this example, but you can define another QName string to recover the target node (or nodes)
                Node nodeNumTel = null;
                for (int i = 0; i < nodeList.getLength(); i++) {
                    //search of text node of this tag name
                    if (nodeList.item(i).getNodeName().compareTo(nameNumTel) == 0) {
                        nodeNumTel = nodeList.item(i);
                        break;
                    }
                }
                //recover the string value (in this case of telephone number)
                String valueNumTelefono = nodeNumTel.getTextContent();
                //clean of value of target text node
                nodeNumTel.setTextContent("");
                //define and inject of CDATA section, in this case encapsulate "+" character
                CDATASection cdata = nodeNumTel.getOwnerDocument().createCDATASection("+");
                //create of new text node
                Text tnode = nodeNumTel.getOwnerDocument().createTextNode(valueNumTelefono);
                //append of CDATASection (in this point is possible to inject many CDATA section on various parts of string (very usefull)
                nodeNumTel.appendChild(cdata);
                nodeNumTel.appendChild(tnode);

                //done!
            }
        };
Run Code Online (Sandbox Code Playgroud)

该回调将从 marshalSendAndReceive 调用

PayloadSoapResponse output = (PayloadSoapResponse ) getWebServiceTemplate()
                .marshalSendAndReceive(input, callbackCDATANumTelefono);
Run Code Online (Sandbox Code Playgroud)

结果是正确发送请求,其中 CDATA 部分有效且未转换为 ascii 字符。

该解决方案的目标是使用 JAXB 技术在 Spring 基础设施上操作 CDATA 部分,而不是使用第三方库。一般来说,回调方法的指令集是非常值得信赖的,并且适合在 Web 服务肥皂的所有环境中注入。关键的方面是使用规范的方法将 SoapMessage 转换为更友好的 DOMSource 来探索节点。还可以使用 XPath 引擎来导航此 DOMSource。

祝你好运!