WSDL概述
WSDL 文档(WSDL = Web 服务描述语言)描述了 Web 服务。WSDL 绑定描述了服务如何绑定到消息传递协议,尤其是 SOAP 消息传递协议。WSDL SOAP 绑定可以是 (RPC)远程过程调用样式或(DOCUMENT)文档样式。SOAP 绑定也可以具有(ENCODED)编码用途或(LITERAL)文本用途。这给出了四种样式/使用模型:
RPC/ENCODED
RPC/LITERAL
DOCUMENT/ENCODED(未在实践中使用)
DOCUMENT/LITERAL
WSDL 区分两种消息样式:文档和 RPC。消息样式会影响 SOAP Body 的内容:
(DOCUMENT)文档样式: SOAP 主体包含一个或多个称为部件的子元素。正文包含的内容没有 SOAP 格式规则;它包含发送方和接收方同意的任何内容。
(RPC)远程过程调用样式: RPC 意味着 SOAP 主体包含一个元素,该元素带有被调用的方法或操作的名称。该元素又包含该方法/操作的每个参数的元素。
对于使用序列化/反序列化来抽象出数据线格式的应用程序,还有一种选择:序列化格式。有两种流行的序列化格式:
(ENCODED)编码用途: SOAP 编码是一组序列化。规则指定对象、结构、数组和对象图应如何序列化。一般来说,使用 SOAP 编码的应用程序专注于远程过程调用,并且可能会使用 RPC 消息样式。当使用 SOAP 编码时,SOAP 消息在 SOAP 消息中包含数据类型信息。这使得序列化(数据转换)更容易,因为每个参数的数据类型都用参数表示。
(LITERAL)文本用途:数据根据模式进行序列化。在实践中,这种模式通常使用 W3C XML Schema 来表示。SOAP 消息不直接包含任何数据类型信息,只是对所使用模式的引用(命名空间)。为了执行正确的序列化(数据转换),发送者和接收者必须知道模式并且必须使用相同的规则来转换数据。
Java编码实践中可以通过@SOAPBinding(style = Style.RPC, use = Use.LITERAL) 设置 style 和 use 进行设置.
WSDL样例
RPC/ENCODED样例
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://jaxws.rooo000.net/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://jaxws.rooo000.net/" name="Hello3Service"> <types/> <message name="say3"> <part name="arg0" type="xsd:string"/> </message> <message name="say3Response"> <part name="return" type="xsd:string"/> </message> <portType name="Hello3"> <operation name="say3"> <input wsam:Action="http://jaxws.rooo000.net/Hello3/say3Request" message="tns:say3"/> <output wsam:Action="http://jaxws.rooo000.net/Hello3/say3Response" message="tns:say3Response"/> </operation> </portType> <binding name="Hello3PortBinding" type="tns:Hello3"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/> <operation name="say3"> <soap:operation soapAction=""/> <input> <soap:body use="literal" namespace="http://jaxws.rooo000.net/"/> </input> <output> <soap:body use="literal" namespace="http://jaxws.rooo000.net/"/> </output> </operation> </binding> <service name="Hello3Service"> <port name="Hello3Port" binding="tns:Hello3PortBinding"> <soap:address location="http://127.0.0.1:8080/jaxws/hello3"/> </port> </service> </definitions>
RPC/LITERAL样例
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://jaxws.rooo000.net/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://jaxws.rooo000.net/" name="Hello4Service"> <types/> <message name="say4"> <part name="arg0" type="xsd:string"/> </message> <message name="say4Response"> <part name="return" type="xsd:string"/> </message> <portType name="hello4"> <operation name="say4"> <input wsam:Action="http://jaxws.rooo000.net/hello4/say4Request" message="tns:say4"/> <output wsam:Action="http://jaxws.rooo000.net/hello4/say4Response" message="tns:say4Response"/> </operation> </portType> <binding name="hello4PortBinding" type="tns:hello4"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/> <operation name="say4"> <soap:operation soapAction=""/> <input> <soap:body use="literal" namespace="http://jaxws.rooo000.net/"/> </input> <output> <soap:body use="literal" namespace="http://jaxws.rooo000.net/"/> </output> </operation> </binding> <service name="Hello4Service"> <port name="hello4Port" binding="tns:hello4PortBinding"> <soap:address location="http://127.0.0.1:8080/jaxws/hello4"/> </port> </service> </definitions>
DOCUMENT/ENCODED样例
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://jaxws.rooo000.net/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://jaxws.rooo000.net/" name="Hello1Service"> <types> <xsd:schema> <xsd:import namespace="http://jaxws.rooo000.net/" schemaLocation="http://127.0.0.1:8080/jaxws/hello1?xsd=1"/> </xsd:schema> </types> <message name="say1"> <part name="parameters" element="tns:say1"/> </message> <message name="say1Response"> <part name="parameters" element="tns:say1Response"/> </message> <portType name="Hello1"> <operation name="say1"> <input wsam:Action="http://jaxws.rooo000.net/Hello1/say1Request" message="tns:say1"/> <output wsam:Action="http://jaxws.rooo000.net/Hello1/say1Response" message="tns:say1Response"/> </operation> </portType> <binding name="Hello1PortBinding" type="tns:Hello1"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="say1"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="Hello1Service"> <port name="Hello1Port" binding="tns:Hello1PortBinding"> <soap:address location="http://127.0.0.1:8080/jaxws/hello1"/> </port> </service> </definitions>
DOCUMENT/LITERAL样例
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://jaxws.rooo000.net/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://jaxws.rooo000.net/" name="Hello2Service"> <types> <xsd:schema> <xsd:import namespace="http://jaxws.rooo000.net/" schemaLocation="http://127.0.0.1:8080/jaxws/hello2?xsd=1"/> </xsd:schema> </types> <message name="say2"> <part name="parameters" element="tns:say2"/> </message> <message name="say2Response"> <part name="parameters" element="tns:say2Response"/> </message> <portType name="Hello2"> <operation name="say2"> <input wsam:Action="http://jaxws.rooo000.net/Hello2/say2Request" message="tns:say2"/> <output wsam:Action="http://jaxws.rooo000.net/Hello2/say2Response" message="tns:say2Response"/> </operation> </portType> <binding name="Hello2PortBinding" type="tns:Hello2"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="say2"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="Hello2Service"> <port name="Hello2Port" binding="tns:Hello2PortBinding"> <soap:address location="http://127.0.0.1:8080/jaxws/hello2"/> </port> </service> </definitions>
调用jaxws服务
默认调用
脚本中封装了一个webserviceClient对象进行jaxws调用.
var url_1 = 'http://127.0.0.1:8080/jaxws/hello1?wsdl'; var url_2 = 'http://127.0.0.1:8080/jaxws/hello2?wsdl'; var url_3 = 'http://127.0.0.1:8080/jaxws/hello3?wsdl'; var url_4 = 'http://127.0.0.1:8080/jaxws/hello4?wsdl'; var o1 = this.service.soap(url_1, 'say1', 'o2oa'); print('hello1:' + o1[0]); var o2 = this.service.soap(url_2, 'say2', 'o2oa'); print('hello2:' + o2[0]); var o3 = this.service.soap(url_3, 'say3', 'o2oa'); print('hello3:' + o3[0]); var o4 = this.service.soap(url_4, 'say4', 'o2oa'); print('hello4:' + o4[0]);
通过测试可以看到脚本的soap可以正常的调用RPC样式的服务,但是调用document样式的服务失败.
计算错误: Unable to create JAXBContext for generated packages: "net.rooo000.jaxws" 不包含 ObjectFactory.class 或 jaxb.index
这是由于WebAppClassLoader在父classLoader才能loader到jakarta.xml.bind-api导致的,后续版本将修复此问题.
com.x.program.center.jaxrs.agent.ExceptionAgentEval: 代理 id:ccdd72cf-8e14-487d-89f3-53f9c32d7c9a, 名称:jaxws调用测试, 别名:, 计算错误: Unable to create JAXBContext for generated packages: "net.rooo000.jaxws" 不包含 ObjectFactory.class 或 jaxb.index, 脚本:/******************** API Document: http://127.0.0.1/api ********************/ var url_1 = 'http://127.0.0.1:8080/jaxws/hello1?wsdl'; var url_2 = 'http://127.0.0.1:8080/jaxws/hello2?wsdl'; var url_3 = 'http://127.0.0.1:8080/jaxws/hello3?wsdl'; var url_4 = 'http://127.0.0.1:8080/jaxws/hello4?wsdl'; // var o1 = this.service.soap(url_1, 'say1', 'o2oa'); // print('hello1:' + o1[0]); // var o2 = this.service.soap(url_2, 'say2', 'o2oa'); // print('hello2:' + o2[0]); // var o3 = this.service.soap(url_3, 'say3', 'o2oa'); // print('hello3:' + o3[0]); var o4 = this.service.soap(url_4, 'say4', 'o2oa'); print('hello4:' + o4[0]); . at com.x.program.center.jaxrs.agent.ActionExecute.execute(ActionExecute.java:83) ~[classes/:?] at com.x.program.center.jaxrs.agent.AgentAction.execute(AgentAction.java:192) ~[classes/:?] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?] at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?] at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52) ~[jaxrs-ri-2.35.jar:2.35.] ......
目前o2server仅能支持RPC样式的调用,尚不支持DOCUMENT样式的调用.在7.1.0以后版本将支持Document样式调用.
直接通过HTTP POST 调用
这样的场景下可以直接调用http 请求发送数据完成soap请求.
/******************** API Document: http://127.0.0.1/api ********************/ var text = encodeURIComponent('<result><plmid>001</plmid><type>reject</type><message>下一步</message></result>'); var url = 'http://192.168.1.100/Service/OA.asmx/Hello'; var HttpConnection = Java.type('com.x.base.core.project.connection.HttpConnection'); var ArrayList = Java.type("java.util.ArrayList"); var NameValuePair = Java.type("com.x.base.core.project.bean.NameValuePair"); var heads = new ArrayList(); heads.add(new NameValuePair('Content-Type', 'application/x-www-form-urlencoded')); var o = HttpConnection.postAsString(url, heads, "strRetXML=" + text, 300, 300); print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!result start') print(o) print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!result end')
直接发送soap消息体调用jaxws服务
特殊情况下可以使用拼装好的xml格式的soap消息体调用服务.
var soap11 ='<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><RollBackProcess2 xmlns="http://tempuri.org/"><strRetXML>string</strRetXML></RollBackProcess2></soap:Body></soap:Envelope>' var o = this.service.jaxwsXml('http://10.0.10.24/PLMService/OAProcess.asmx',soap11); print('!!!!!!!!!!!!!!!!!!!!!!!call jaxwsXml start'); print(o[0]) print('!!!!!!!!!!!!!!!!!!!!!!!call jaxwsXml end');
若有收获,就点个赞吧