WebService和编程语言中的类相似,它们都实现了一些功能,并且通过方法供给外部调用,不同的是WebService是部署在网络服务器上,而类在同一个进程空间里面。WebService部署在网络上,通过网络进行服务调用,只要遵循了访问协议,任何编程语言都可以访问服务,所以它是编程语言不相关的。
我们可以通过类文件知道一个类提供了哪些方法,那怎么知道WebService提供了哪些服务供外部调用呢?每一个WebService都有一个WSDL文件,WSDL全称Web Services Description Language(网络服务描述语言),WSDL有两个作用:
- 描述了WebService提供的服务,就像类里面的方法,包含名字、参数、返回值。
- 描述了访问服务的方法。
下面是一个WSDL的示例文件:
WSDL包含了五部分内容:
- types
- message
- portType
- binding
- service
其中portType里面的内容描述了WebService提供的服务,上例中的portType内容可以翻译为Java类,如下:
==> 对应类名
==> 对应方法名 ......
//翻译后的portType内容 public class HelloWorld { public ... sayHelloWorld(...) { // ...... } }
可以看到sayHelloWorld方法中的参数和返回值使用了”…”,这是因为通过portType无法直接得到参数和返回值,所以用“…”代替。至于具体的参数和返回值怎么获取,我们在后面讲解,姑且先当做void看待。现在知道了WebService提供的方法,要怎么调用它呢?还是得看WSDL,我们知道WebService是部署在网络上的,访问WebService就需要进行网络数据交互,网络数据交互需要通信协议。 WSDL中的binding部分描述了通信协议,WebService通常是HTTP + SOAP(Simple Object Access Protocol 简单对象访问协议)协议来进行数据交互,SOAP基于XML它被设计成在WEB上交换结构化的和固化的信息。本例中WebService也是采用HTTP+SOAP协议进行数据交互,本文中WSDL的binding内容如下所示:
下面是一个 HTTP+SOAP 示例:
POST URI HTTP/1.1 Accept: text/xml, multipart/related Content-Type: text/xml; charset=utf-8 SOAPAction: "Action" User-Agent: JAX-WS RI 2.2.7-b01 svn-revision#${svn.Last.Changed.Rev} Host: localhost:9090 Connection: keep-alive Content-Length: xxx
自定义元素内容
可以看到HTTP+SOAP就是把SOAP放入HTTP的body部分使用POST发送给WebService服务器。SOAP协议的Body内容由使用者定义,WSDL为每个WebService方法的调用和返回定义了SOAP body格式也就是定义了一个XML元素,只要找到 WebService 方法对应的自定义元素,就能封装SOAP协议了。通过WSDL的portType 、message两部分内容可以找到方法对应的自定义元素,本例中这两部分内容如下所示:
types从http://localhost:9090/HelloWorld?xsd=1引入了元素定义,引入的内容如下:
可以看到sayHelloWorld元素包含一个类型为string的arg0元素,表示 sayHelloWorld 方法有一个string类型的参数。saysayHelloWorldResponse包含一个类型为string的return元素, 表示 sayHelloWorld 返回一个string类型的值。知道了参数和方法Webservice描述的方法就可以用Java完整的翻译出来,如下:
//WebService提供的服务 public class HelloWorld { public String sayHelloWorld(String arg0) { // ...... } }
知道了 sayHelloWorld 元素和 saysayHelloWorldResponse 元素的定义以后我们就知道怎么封装Soap了,调用 sayHelloWorld 并且传参数jack的Soap封装为:
jack
返回时的Soap封装如下:
Hello, world, from jack
可以看到sayHelloWorld返回值是“Hello, world, from jack”。封装好Soap协议以后就可以往Webservice服务器发送协议了,但是我们目前还不知道Webservice的地址,通过WSDL的service部分可以获取Webservice的地址,本例中的service内容如下:
wsam:Action内容即是HTTP头部的SOAPAction。至此我没可以组装出完整的HTTP+SOAP,完整的调用协议内容如下:
POST /HelloWorld HTTP/1.1 Accept: text/xml, multipart/related Content-Type: text/xml; charset=utf-8 SOAPAction: "http://example/HelloWorld/sayHelloWorldRequest" User-Agent: JAX-WS RI 2.2.7-b01 svn-revision#${svn.Last.Changed.Rev} Host: localhost:9090 Connection: keep-alive Content-Length: xxx
jack
完整的返回协议如下:
HTTP/1.1 200 OK Date: Fri, 17 May 2019 08:34:13 GMT Transfer-encoding: chunked Content-type: text/xml; charset=utf-8
Hello, world, from jack
虽然WebService的底层很复杂,但是大多数编程语言都有现成的框架帮助我们完成底层的细节,具体的我们在编写WebService时通常只用创建一个类并且实现类的一些方法, 框架会根据类自动生成WSDL 。WebService的调用也很简单,框架可以根据WSDL生成一个类,我们只需实例化对象然后调用方法获取返回值,和使用普通的类没什么两样。
- service,提供了WebService的访问地址 。
- portType,定义了WebService提供的服务。
- binding,定义了WebService通信协议 。
- message,定义了每个服务调用的和返回的格式,常通过引用一个自定义元素,由自定义的元素 (element) 描述格式。
- types,定义了message引用的各种自定义元素(element)。
本文描述的WSDL使用Document literal wapped 格式的协议,它还支持RPC literal/encode 协议,关于两种协议的区别和各自的应用场景会在后面的文章中讲解。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/212960.html原文链接:https://javaforall.net
