什么是WebService,顾名思义,就是基于Web的服务,它使用Http方式接收和响应外部系统的某种请求,从而实现远程调用。WebService实际上就是依据某些标准,不关心对方使用的是何种语言,实现对外部其它应用程序提供跨平台、跨语言服务的一种技术。html
使用WebService,咱们能够调用互联网上查询天气信息的Web服务,而后将其嵌入到咱们的程序中,当用户从咱们的网点看到天气信息的时候,他会觉得咱们为他提供了不少的信息服务,但其实咱们什么也没有作,只是简单调用了一下服务器上的一端代码而已。java
以前曾经说过Spring的远程调用,实际上WebService的功能和Spring的远程调用彻底相同,WebService的本质也就是远程调用,只不过Spring和WebService的实现原理不相同而已。比较WebService和Spring的远程调用:web
1.Spring远程调用在网络上传输的是“串行化对象”,而WebService在网络上传输的是XML字符串。spring
2.Spring远程调用效率更高,由于它传输的是真正的“数据”,而为了知足传输的XML的规范,WebService须要将数据进行一层层的封装,好比服务端须要传递给客户端一个大小为100的List<Student>list,使用Spring的远程调用直接传递该对象到网络流便可,可是使用WebService却必须得将数据进行严格的规整以使其知足XML的规范(示例,实际上的传输规范并非这样):浏览器
<List> <Student> <id>1</id> <name>小张</name> <sex>男</sex> <age>13</age> <phone>111111111</phone> <email>11111@123.com</email> </Student> <Student> <id>2</id> <name>小李</name> <sex>女</sex> <age>15</age> <phone>2222222</phone> <email>22222@123.com</email> </Student> ...此处省略98个Student... </List>
这样致使的问题就是传输了大量的“无用字符”,也就是大量的标签了,实际上在上述的例子中标签所占据的字符数量几乎和要传递的数据量同样多,其效率之低是显而易见的。服务器
3.spring远程调用要求两个程序都使用spring环境(java环境),可是WebService能够实现跨平台通讯,也就是说即便两个程序之间使用的不是同一种语言,好比一个PHP的程序和Java的程序,他们也可以相互通讯,这是WebService的最大卖点。网络
4.在不考虑通用性的状况下,若是程序两端都使用了Spring,那么就使用Spring的远程调用;若是平台语言不相同,则使用WebService;若是考虑到通用性,即须要向大众提供服务,那么必定得使用Webservice。eclipse
全名为WebService Description Language ,翻译过来就是Web服务描述语言。它使用XML描述服务的地址,服务提供的方法以及参数列表、返回值类型等,实际上就是一个Web服务的说明书,好比webxml.com.cn网站提供了天气预报查询的服务,对应的WSDL就是:http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl工具
全名为Simple Object Access Protocol,翻译过来就是简单对象访问协议,SOAP是一种XML语言的协议,用于在网络上传输数据。学习
SOAP=XML+HTTP
SOAP是基于Http协议的,SOAP的组成:Envelope,这是必须的部分,以XML根元素的形式出现;Headers,可选;Body,必须的部分,包含要执行的服务器上的方法和发送到服务器上的数据。
1 package com.kdyzm.ws; 2 3 import javax.jws.WebService; 4 import javax.xml.ws.Endpoint; 5 6 @WebService 7 public class MyWsServer { 8 public String calculate(int input){ 9 return input*input+""; 10 } 11 public static void main(String[] args) { 12 Endpoint.publish("http://localhost:9090/ws", new MyWsServer()); 13 System.out.println("server ready ......"); 14 } 15 }
OK,一个最简单的WebService服务就发布了。
对以上的代码的说明:在Java中,使用EndPoint类发布服务,使用该类发布服务的方法是publish方法,该方法由两个参数,一个参数是发布服务的地址,另一个参数是提供服务的类;当执行到publish方法的时候,程序会新开一个线程专门用于提供服务,主线程会继续执行下去,因此下面的打印的代码会不受影响的执行。
另外,提供服务的类至少应当提供一个非静态方法不然服务启动不起来。
如何查看wsdl?在浏览器上输入http://localhost:9090/ws?wsdl,回车便可查看wsdl内容:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is 3 JAX-WS RI 2.1.6 in JDK 6. --> 4 <!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is 5 JAX-WS RI 2.1.6 in JDK 6. --> 6 <definitions 7 xmlns="http://schemas.xmlsoap.org/wsdl/" 8 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 9 xmlns:tns="http://ws.kdyzm.com/" 10 xmlns:xsd="http://www.w3.org/2001/XMLSchema" 11 targetNamespace="http://ws.kdyzm.com/" 12 name="MyWsServerService"> 13 <types> 14 <xsd:schema> 15 <xsd:import namespace="http://ws.kdyzm.com/" 16 schemaLocation="http://localhost:9090/ws?xsd=1"></xsd:import> 17 </xsd:schema> 18 </types> 19 <message name="calculate"> 20 <part name="parameters" element="tns:calculate"></part> 21 </message> 22 <message name="calculateResponse"> 23 <part name="parameters" element="tns:calculateResponse"></part> 24 </message> 25 <portType name="MyWsServer"> 26 <operation name="calculate"> 27 <input message="tns:calculate"></input> 28 <output message="tns:calculateResponse"></output> 29 </operation> 30 </portType> 31 <binding name="MyWsServerPortBinding" type="tns:MyWsServer"> 32 <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 33 style="document"></soap:binding> 34 <operation name="calculate"> 35 <soap:operation soapAction=""></soap:operation> 36 <input> 37 <soap:body use="literal"></soap:body> 38 </input> 39 <output> 40 <soap:body use="literal"></soap:body> 41 </output> 42 </operation> 43 </binding> 44 <service name="MyWsServerService"> 45 <port name="MyWsServerPort" binding="tns:MyWsServerPortBinding"> 46 <soap:address location="http://localhost:9090/ws"></soap:address> 47 </port> 48 </service> 49 </definitions>
若是能力足够高的话,直接阅读wsdl文件就可以直接向服务器请求并获取服务了,可是通常来讲这么作很是的复杂,为了提升开发效率,在java环境下咱们使用wsimport命令生成本地调用代码,而后直接使用这些生成的代码就能够了。
wsimport命令是jdk提供的命令,可是应当注意的是,该命令只是在jdk1.6.0_24及以上的版本才提供,因此若是使用了jdk1.5的版本确定不能支持。
wsimport命令可以解析指定的wsdl文件并将根据wsdl文件中的配置生成对应的java代码并将其编译成class文件。
wsimport命令的经常使用参数:
-d <目录名>:将会生成.class文件,默认参数,就算不使用该参数也会自动加上。
-s <目录名>:将会生成java文件
-p <生成的包名>:将生成的类放到指定的目录下。
步骤:使用命令生成本地调用代码:wsimport -s . http://localhost:9090/ws?wsdl
任务执行完毕以后,会在当前目录下生成一个文件夹,文件夹中存放着全部将要使用到的java类和编译以后的.class文件
将全部的class文件删除掉,以后将文件夹直接拷贝到项目中便可使用。
注意事项:若是是咱们本身发布的服务,咱们使用wsimport命令确定可以解析成功,可是若是咱们使用网络上其它站点提供的服务,那么在生成本地调用代码的时候颇有可能会生成失败。好比咱们常常回到这个网站上找相关的免费服务:http://www.webxml.com.cn/zh_cn/index.aspx,在这个网站上有一个“天气预报查询”的服务,它也提供了一个wsdl文档,可是咱们在解析该文档生成本地调用代码的时候会生成失败。解决方法参考:http://blog.sina.com.cn/s/blog_924d6a570102w203.html
以以前发布的服务为例。
新建一个普通类型的java工程,将文件夹中的全部.class文件删除掉以后,将包括文件夹在内的全部文件都拷贝到项目中。
将生成的代码拷贝到项目中以后颇有可能会报错,提示Service类中没有对应的构造方法,解决方法参考 http://blog.sina.com.cn/s/blog_924d6a570102w21v.html
接下来只须要使用这些类就能够了,如何使用这些类,应当参考wsdl文档。
客户端的测试代码:
1 package com.kdyzm.test; 2 3 import com.kdyzm.ws.MyWsServer; 4 import com.kdyzm.ws.MyWsServerService; 5 6 public class Main { 7 public static void main(String[] args) { 8 MyWsServerService myWsServerService=new MyWsServerService(); 9 MyWsServer myWsServer=myWsServerService.getMyWsServerPort(); 10 String result=myWsServer.calculate(2); 11 System.out.println(result); 12 } 13 }
控制台输出结果是4(客户端)。
java ee版本的eclipse中(java ee视图)提供了一种专门用于WebService的浏览器,名字为Web Service Exployer
直接进入到该视图中,而后切换到WSDL Page视图,并点击clear按钮,最终显示的界面以下:
在地址栏中输入wsdl的地址,这里是http://localhost:9090/ws?wsdl,并回车
接下来会显示出全部的服务(类)和服务下的方法,图略。
下一步就是单击方法名,而后给方法添加实参发出请求以后查看请求的时候的请求信息和响应信息,这里仍是以2为例,最终结果是这样的:
显示返回值是4,而后单击source
这也不是我想要的,直接对着框框右键“查看源代码”,能够看到SOAP的请求信息和SOAP的响应信息:
请求信息:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://ws.kdyzm.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <q0:calculate> <arg0>2</arg0> </q0:calculate> </soapenv:Body> </soapenv:Envelope>
响应信息:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:calculateResponse xmlns:ns2="http://ws.kdyzm.com/"> <return>4</return> </ns2:calculateResponse> </S:Body> </S:Envelope>
能够看到不管是请求信息仍是响应信息都是以Envelope为根节点,并且接下来都是Body节点,这点是符合SOAP协议的规范的。