o2server 调用外部webservice(jaxws)服务
由 0x400 发布于
WSDL文档(WSDL = Web服务描述语言)用于描述Web服务。其中,WSDL绑定说明了服务与消息传递协议(特别是SOAP消息传递协议)的绑定方式。WSDL SOAP绑定存在以下两种风格及用途:
- **风格**:
- **(RPC)远程过程调用**:意味着SOAP主体包含一个元素,该元素带有被调用的方法或操作的名称,此元素又包含该方法/操作的每个参数的元素。
- **(DOCUMENT)文档样式**:SOAP主体包含一个或多个称为部件的子元素,正文包含的内容没有SOAP格式规则,包含发送方和接收方约定的任意内容。
- **用途**:
- **(ENCODED)编码用途**:SOAP编码是一组序列化规则,指定对象、结构、数组和对象图应如何序列化。使用SOAP编码的应用程序通常侧重于远程过程调用,可能会搭配RPC消息样式,且SOAP消息中包含数据类型信息,便于序列化。
- **(LITERAL)文本用途**:数据依据模式进行序列化,实践中常使用W3C XML Schema表示。SOAP消息不直接包含数据类型信息,仅含对所用模式的引用(命名空间),要求发送者和接收者知晓模式并遵循相同规则转换数据。
综合上述,形成了四种样式/使用模型:
1. RPC/ENCODED
2. RPC/LITERAL
3. DOCUMENT/ENCODED(未在实践中使用)
4. DOCUMENT/LITERAL
在Java编码实践中,可通过`@SOAPBinding(style = Style.RPC, use = Use.LITERAL)`设置style和use。
# WSDL样例
## RPC/ENCODED样例
```xml
<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样例
```xml
<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样例
```xml
<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.00.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样例
```xml
<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调用。

```javascript
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`才能加载到`jakarta.xml.bind-api`导致的,后续版本将修复此问题。详细错误堆栈信息如下:
```plain
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请求。
```javascript
/********************
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
评论