技术文章

当前位置:首页>帮助手册>技术文章

O2server 调用外部webservice(jaxws)服务

时间:2022-04-22   

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


上一篇:平台维护-流转中工作数据的查询、操作和管理

下一篇:o2server 消息和消息处理器使用,如何将消息推送到webSocket 推送消息 日历消息 自建表 welink 钉钉 企业微信 公众号 邮件 mq restful jdbc hadoop或自建消