大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全家桶1年46,售后保障稳定
1.Web Service的一些相关概念
web service:远程调用的一种方案。一种解决跨平台、跨语言间的分布式系统的集成(整合)方案
esb:enterprise service bus企业服务总线
soap:simple object access protocal简单对象访问协议(http + xml)
soa:service oriented acrchietecture(面向服务的架构)
wsdl:web service description language ,web service 描述语言
2.WSDL详解
大部分内容来自:http://www.ibm.com/developerworks/cn/webservices/ws-wsdl/index.html
1)Web Service “Stack”
其中,绿色部分是先前已经定义好的并且广泛使用的传输层和网络层的标准:IP、HTTP、SMTP等。而蓝色部分是目前开发的Web服务的相关标准协议,包括服务调用协议SOAP、服务描述协议WSDL和服务发现/集成协议UDDI,以及服务工作流描述语言WSFL。而橙色部分描述的是更高层的待开发的关于路由、可靠性以及事务等方面的协议。黄色部分是各个协议层的公用机制,这些机制一般由外部的正交机制来完成。
其中,一个可以使用的Web服务应当按照需要选用若干层次的功能,而无需所有的特性。但是无论如何为了实现一个一般意义上的Web服务,具备Web服务的基础特性:跨平台调用和接口可机器识别,那么必需使用WSDL和SOAP。SOAP是用来最终完成Web服务调用的,而WSDL则是用于描述如何使用SOAP来调用Web服务的。
WSDL 是一种XML Application,他将Web服务描述定义为一组服务访问点,客户端可以通过这些服务访问点对包含面向文档信息或面向过程调用的服务进行访问(类似远程过程调用)。WSDL首先对访问的操作和访问时使用的请求/响应消息进行抽象描述,然后将其绑定到具体的传输协议和消息格式上以最终定义具体部署的服务访问点。相关的具体部署的服务访问点通过组合就成为抽象的Web服务。
在具体使用中,我们可以对 WSDL 进行扩展(类似SOAP的可扩展性),这样无论通信时使用何种消息格式或网络协议,都可以对服务访问点及其使用的消息格式进行描述。在WSDL的框架中,可以使用任意的消息格式和网络协议,如同SOAP中可以使用任意的网络协议一样。在WSDL规范中,定义了如何使用SOAP消息格式、HTTP GET/POST消息格式以及MIME格式来完成Web服务交互的规范。
2)WSDL概述
由于通信协议和消息格式在 Web 技术圈子里已经达到了标准化,我们知道在通常的开发过程中,对于对象的Interface一定具备相应的SDK描述文档,Web服务也是一种对象,只不过它是被部署在Web上而已。很自然的,我们也完全需要有对Web服务这个对象的界面的SDK描述文档。然而这两者又不尽相同,一来目前在Web上的应用已经完全接受了XML这个基本的标准,基本上所有新出台的技术都是基于XML标准的,二来Web服务的目标是即时装配,松散耦合以及自动集成的,这意味着SDK描述文档应当是具备被机器识别的能力的。
也就是说,对于使用标准化的消息格式/通信协议的Web服务,它需要以某种结构化的方式(即XML)对Web服务的调用/通信加以描述,而且实现这一点也显得非常重要,这是Web服务即时装配的基本保证。WSDL正是这样一种描述语言,WSDL 定义了一套基于 XML的 语法,将Web服务描述为能够进行消息交换的服务访问点的集合,从而满足了这种需求。WSDL 服务定义为分布式系统提供了可机器识别的SDK文档,并且可用于描述自动执行应用程序通信中所涉及的细节。
WSDL 文档将Web服务定义为服务访问点或端口的集合。在 WSDL 中,由于服务访问点和消息的抽象定义已从具体的服务部署或数据格式绑定中分离出来,因此可以对抽象定义进行再次使用:消息,指对交换数据的抽象描述;而端口类型,指操作的抽象集合。用于特定端口类型的具体协议和数据格式规范构成了可以再次使用的绑定。将Web访问地址与可再次使用的绑定相关联,可以定义一个端口,而端口的集合则定义为服务。因此,WSDL 文档在Web服务的定义中使用下列元素:
- Types – 数据类型定义的容器,它使用某种类型系统(一般地使用XML Schema中的类型系统)。
- Message – 通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构。
- Operation – 对服务中所支持的操作的抽象描述,一般单个Operation描述了一个访问入口的请求/响应消息对。
- PortType – 对于某个访问入口点类型所支持的操作的抽象集合,这些操作可以由一个或多个服务访问点来支持。
- Binding – 特定端口类型的具体协议和数据格式规范的绑定。
- Port – 定义为协议/数据格式绑定与具体Web访问地址组合的单个服务访问点。
- Service – 相关服务访问点的集合。
大家可以参考下图,来理解一下WSDL文档的结构组织:
其中,Types是一个数据类型定义的容器,包含了所有在消息定义中需要的XML元素的类型定义.
Message具体定义了在通信中使用的消息的数据结构,Message元素包含了一组Part元素,每个Part元素都是最终消息的一个组成部分,每个Part都会引用一个DataType来表示它的结构。Part元素不支持嵌套(可以使用DataType来完成这方面的需要),都是并列出现。
PortType具体定义了一种服务访问入口的类型,何谓访问入口的类型呢?就是传入/传出消息的模式及其格式。一个PortType可以包含若干个Operation,而一个Operation则是指访问入口支持的一种类型的调用。在WSDL里面支持四种访问入口调用的模式:
- 单请求;
- 单响应;
- 请求/响应;
- 响应/请求。
在这里请求指的是从客户端到Web服务端,而响应指的是从Web服务端到客户端。PortType的定义中会引用消息定义部分的一个到两个消息,作为请求或响应消息的格式。比如,一个股票查询的访问入口可能就会支持两种请求消息,一种请求消息中指明股票代码,而另一种请求消息中则会指明股票的名称,响应消息可能都是股票的价格等等。
以上三种结构描述了调用Web服务的抽象定义,这三部分与具体Web服务部署细节无关,是可复用的描述(每个层次都可以复用)。如果与一般的对象语言做比较的话,这部分可以堪称是IDL描述的对象,描述了对象的接口标准,但是到底对象是用哪种语言实现,遵从哪种平台的细节规范,被部署在哪台机器上则是后面的元素所描述的。
Service描述的是一个具体的被部署的Web服务所提供的所有访问入口的部署细节,一个Service往往会包含多个服务访问入口,而每个访问入口都会使用一个Port元素来描述。
Port描述的是一个服务访问入口的部署细节,包括通过哪个Web地址(URL)来访问,应当使用怎样的消息调用模式来访问等。其中消息调用模式则是使用Binding结构来表示。
Binding结构定义了某个PortType与某一种具体的网络传输协议或消息传输协议相绑定,从这一层次开始,描述的内容就与具体服务的部署相关了。比如可以将PortType与SOAP/HTTP绑定,也可以将PortType与MIME/SMTP相绑定等。
在介绍了WSDL的主要元素之后,大家会发现,WSDL的设计理念完全继承了以XML为基础的当代Web技术标准的一贯设计理念:开放。WSDL允许通过扩展使用其他的类型定义语言(不光是XML Schema),允许使用多种网络传输协议和消息格式(不光是在规范中定义的这些:SOAP/HTTP,HTTP-GET/POST以及MIME等)。同时WSDL也应用了当代软件工程中的复用理念,分离了抽象定义层和具体部署层,使得抽象定义层的复用性大大增加。比如我们可以先使用抽象定义层为一类Web服务进行抽象定义(比如UDDI Registry,抽象定义肯定是完全一致的遵循了UDDI规范),而不同的运营公司可以采用不同的具体部署层的描述结合抽象定义完成其自身的Web服务的描述。
一个web services要被其它应用调用,就必须告诉其它应用如何去调用web services中的webmethod,比如这个web services中包含哪些可以调用的方法,每个方法的方法签名是怎样的,方法是用的输入输出参数的类型又是什么等等,这些都是通过web services的WSDL来进行描述的。
要查看一个web services的WSDL可以向web services所在的asmx文件的URL发送http请求,并附带?wsdl参数即可,比如:http://biztalkr2:81/WSTest/Service1.asmx?WSDL
来查看一下上面这个web services的WSDL中跟TwoWayMethod相关的部分:
Figue 1. WSDL中跟TwoWayMethod相关的部分
这个WSDL的结构需要按照从下面往上面的顺序看。
2.1. portType标签
portType标签用来描述整个的web services,portType的name属性即为这个web services类的类名。这个标签下包含了所有的可用方法,每个operation标签表示一个方法。
2.2. operation标签
每一个operation标签表示web services里的一个webmethod方法,operation标签的name属性是这个webmethod的方法名。
2.3. Input和output标签
Input和output标签分别表示一个operation(webmethod方法)的输入和输出的参数集合,这里叫做消息,不管输入参数有几个,每个参数有多么复杂,只有一个表示这些输入参数的消息,就是input标签的message属性表示的那个消息。对于输出消息也一样。
2.4. Message标签
方法的输入输出参数都用一个消息来表示,message标签表示一个这样的消息,message标签按下面有个part标签,用来具体指示这个消息在schema中的类型,类型以element形式表现出来,即part标签的element属性指定的那个element。
对于输入参数消息,part标签的element属性命名同webmethod方法名。
对于输出参数消息,part标签的element属性命名同webmethod方法名 + response。
表示类型的element都被集中放置在types标签内。
2.5. types标签
此标签用来描述所有webmethod所要用到的类型,都以element来描述类型。比如:
public string[] TwoWayMethod(float a,Person person)
这个webmethod的输入参数有两个:float a,Person person,在WSDL的中的类型表现是这样的:
<s:element name=”TwoWayMethod“>
<s:complexType>
<s:sequence>
<s:element minOccurs=”1” maxOccurs=”1” name=”a” type=”s:float” />
<s:element minOccurs=”0” maxOccurs=”1” name=”person” type=”tns:Person” />
</s:sequence>
</s:complexType>
</s:element>
其中a元素是简单的float类型,不需要另加说明。
person元素是Person类型,Person类型又是个complex类型,在types标签里还包括了这个Person类型的定义。只要是消息中引用到的非简单类型,都需要在types中进行定义描述。
下面的WSDL即为我上篇文章HelloWorld Webservice的描述文档:
- <?xml version=‘1.0’ encoding=‘UTF-8’?><wsdl:definitions name=“HelloWorldService” targetNamespace=“http://test.demo1/” xmlns:ns1=“http://schemas.xmlsoap.org/soap/http” xmlns:soap=“http://schemas.xmlsoap.org/wsdl/soap/” xmlns:tns=“http://test.demo1/” xmlns:wsdl=“http://schemas.xmlsoap.org/wsdl/” xmlns:xsd=“http://www.w3.org/2001/XMLSchema”>
- <wsdl:types>
- <xs:schema elementFormDefault=“unqualified” targetNamespace=“http://test.demo1/” version=“1.0” xmlns:tns=“http://test.demo1/” xmlns:xs=“http://www.w3.org/2001/XMLSchema”>
- <xs:element name=“sayHello” type=“tns:sayHello”/>
- <xs:element name=“sayHelloResponse” type=“tns:sayHelloResponse”/>
- <xs:complexType name=“sayHello”>
- <xs:sequence>
- <xs:element minOccurs=“0” name=“arg0” type=“xs:string”/>
- </xs:sequence>
- </xs:complexType>
- <xs:complexType name=“sayHelloResponse”>
- <xs:sequence>
- <xs:element minOccurs=“0” name=“return” type=“xs:string”/>
- </xs:sequence>
- </xs:complexType>
- </xs:schema>
- </wsdl:types>
- <wsdl:message name=“sayHelloResponse”>
- <wsdl:part element=“tns:sayHelloResponse” name=“parameters”>
- </wsdl:part>
- </wsdl:message>
- <wsdl:message name=“sayHello”>
- <wsdl:part element=“tns:sayHello” name=“parameters”>
- </wsdl:part>
- </wsdl:message>
- <wsdl:portType name=“HelloWorld”>
- <wsdl:operation name=“sayHello”>
- <wsdl:input message=“tns:sayHello” name=“sayHello”>
- </wsdl:input>
- <wsdl:output message=“tns:sayHelloResponse” name=“sayHelloResponse”>
- </wsdl:output>
- </wsdl:operation>
- </wsdl:portType>
- <wsdl:binding name=“HelloWorldServiceSoapBinding” type=“tns:HelloWorld”>
- <soap:binding style=“document” transport=“http://schemas.xmlsoap.org/soap/http”/>
- <wsdl:operation name=“sayHello”>
- <soap:operation soapAction=“” style=“document”/>
- <wsdl:input name=“sayHello”>
- <soap:body use=“literal”/>
- </wsdl:input>
- <wsdl:output name=“sayHelloResponse”>
- <soap:body use=“literal”/>
- </wsdl:output>
- </wsdl:operation>
- </wsdl:binding>
- <wsdl:service name=“HelloWorldService”>
- <wsdl:port binding=“tns:HelloWorldServiceSoapBinding” name=“HelloWorldPort”>
- <soap:address location=“http://localhost:8080/helloWorld”/>
- </wsdl:port>
- </wsdl:service>
- </wsdl:definitions>
Web service中一个wsdl对应一个web service地址,可以想象成一个商店,商店里面出售很多手机(portTypes),每个手机上有很多功能(opeations),每个功能对应很多输入和输出参数(message)
这里没有类,只有端口。。。没有方法,只有端口里面的操作,没有参数,只有传递给端口中某个操作的消息
xml文档第一句:
definitions–WSDL文档的根元素,该元素的属性指明了wsdl文档的名称,文档的目标名字空间,以及WSDL文档应用的名字空间的速记定义。它指明了此WebService的名称为:HelloWorldImplService
然后找到名为“HelloWorldImplService”的service具体定义如下所示:
- <wsdl:service name=“HelloWorldImplService”>
- <wsdl:port binding=“tns:HelloWorldImplServiceSoapBinding” name=“HelloWorldImplPort”>
- <soap:address location=“http://localhost:8080/helloWorld” />
- </wsdl:port>
- </wsdl:service>
service—相关port元素的集合,用户组织endpoint定义。
port–通过binding和物理地址定义的endpoint,这个元素将所有抽象定义聚集在一起
这部分是具体的Web服务的定义,在这个名为 HelloWorldImplService的Web服务中,提供了一个服务访问入口,访问地址是”http://localhost:8080/helloWorld”,使用的消息模式是由前面的binding
“HelloWorldImplServiceSoapBinding”所定义的。
- <wsdl:binding name=“HelloWorldImplServiceSoapBinding” type=“tns:HelloWorld”>
- <soap:binding style=“document” transport=“http://schemas.xmlsoap.org/soap/http” />
- <wsdl:operation name=“sayHello”>
- <soap:operation soapAction=“” style=“document” />
- <wsdl:input name=“sayHello”>
- <soap:body use=“literal” />
- </wsdl:input>
- <wsdl:output name=“sayHelloResponse”>
- <soap:body use=“literal” />
- </wsdl:output>
- </wsdl:operation>
- </wsdl:binding>
binding—一个endpoint的实际数据格式说明,一个binding元素定义如何将一个抽象消息映射到一个具体数据格式。该元素指明诸如参数顺序,返回值等信息。
每个被支持的信息格式和信息传送方式组合,就叫做 binding (就是如果你要和商店里的服务员沟通,那么你们必须规定好用什么语言沟通,binging就是把某个服务员(比如销售nokia的服务员)和某种语言绑定wsdlsoap:binding 就是用 soap语言通话 )
这段xml定义的操作“sayHello”使用的是SoapDocumentProtocol消息格式(style=”document”)。输入和输出参数格式都是“Literal”(use=”literal”)
关于:SQAP的消息格式可以参考文章:http://www.cnblogs.com/linyawen/archive/2011/07/20/2111177.html
- <wsdl:portType name=“HelloWorld”>
- <wsdl:operation name=“sayHello”>
- <wsdl:input message=“tns:sayHello” name=“sayHello” />
- <wsdl:output message=“tns:sayHelloResponse” name=“sayHelloResponse” />
- </wsdl:operation>
- </wsdl:portType>
portType—描述服务逻辑接口的operation元素的集合。HelloWorld只有一个操作sayHello.
这部分定义了服务访问点的调用模式的类型,表明 HelloWorld Service的sayHello入口类型是请求/响应模式,请求消息是sayHello,而响应消息是sayHelloResponse。
- <wsdl:message name=“sayHelloResponse”>
- <wsdl:part element=“tns:sayHelloResponse” name=“parameters” />
- </wsdl:message>
- <wsdl:message name=“sayHello”>
- <wsdl:part element=“tns:sayHello” name=“parameters” />
- </wsdl:message>
这部分是消息格式的抽象定义,其中定义了两个消息格式:
- sayHelloResponse( 响应消息格式 ): 由一个消息片断组成,该消息片断的名字是parameters,包含的具体元素类型是sayHelloResponse。
- sayHello( 请求消息格式 ) : 由一个消息片断组成,该消息片断的名字是 parameters ,包含的具体元素类型是sayHello。
- <xs:element name=“sayHello” type=“tns:sayHello” />
- <xs:element name=“sayHelloResponse” type=“tns:sayHelloResponse” />
- <xs:complexType name=“sayHello”>
- <xs:sequence>
- <xs:element minOccurs=“0” name=“arg0” type=“xs:string” />
- </xs:sequence>
- </xs:complexType>
- <xs:complexType name=“sayHelloResponse”>
- <xs:sequence>
- <xs:element minOccurs=“0” name=“return” type=“xs:string” />
- </xs:sequence>
- </xs:complexType>
上面这部分是数据类型的定义,其中为定义了两个元素的结构:
- sayHello(请求参数的类型): 将该元素定义为包含一个字符串元素(arg0)的复合类型元素。
- sayHelloResponse(响应参数的类型): 将该元素定义为包含一个字符串元素(return)的复合类型元素。
- <xs:element minOccurs=“0” name=“arg0” type=“xs:string” />
<xs:element minOccurs=”0″ name=”return” type=”xs:string” />
其中的name=”arg0″, name=”return”中的“arg0”,“return”是可以指定的,因为我前面一章的HelloWorld输入输出参数都是使用的默认的参数名,所以生成的xml是这样子。
如果HelloWorld接口中的方法修改成
- public @WebResult(name=“responseResult”)String sayHello(@WebParam(name=“name”)String name) ;
也就是给输入参数与返回结果指定一个选定的名字,则生成的xml如下所示:
- <xs:complexType name=“sayHello”>
- <xs:sequence>
- <xs:element minOccurs=“0” name=“name” type=“xs:string”/>
- </xs:sequence>
- </xs:complexType>
- <xs:complexType name=“sayHelloResponse”>
- <xs:sequence>
- <xs:element minOccurs=“0” name=“responseResult” type=“xs:string”/>
- </xs:sequence>
- </xs:complexType>
4.请求及响应的具体消息格式如下所示:
请求消息:
- – <soapenv:Envelope xmlns:soapenv=“http://schemas.xmlsoap.org/soap/envelope/” xmlns:q0=“http://test.demo1/” xmlns:xsd=“http://www.w3.org/2001/XMLSchema” xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”>
- – <soapenv:Body>
- – <q0:sayHello>
- <arg0>xxl</arg0>
- </q0:sayHello>
- </soapenv:Body>
- </soapenv:Envelope>
响应消息:
- – <soap:Envelope xmlns:soap=“http://schemas.xmlsoap.org/soap/envelope/”>
- – <soap:Body>
- – <sayHelloResponse xmlns:ns2=“http://test.demo1/”>
- <return>hello xxl</return>
- </sayHelloResponse>
- </soap:Body>
- </soap:Envelope>
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/234249.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...