【Java EE 学习 80 上】【WebService】
一、WebService概述
什么是WebService,顾名思义,就是基于Web的服务,它使用Http方式接收和响应外部系统的某种请求,从而实现远程调用。WebService实际上就是依据某些标准,不关心对方使用的是何种语言,实现对外部其它应用程序提供跨平台、跨语言服务的一种技术。
使用WebService,我们可以调用互联网上查询天气信息的Web服务,然后将其嵌入到我们的程序中,当用户从我们的网点看到天气信息的时候,他会以为我们为他提供了很多的信息服务,但其实我们什么也没有做,只是简单调用了一下服务器上的一端代码而已。
之前曾经说过Spring的远程调用,实际上WebService的功能和Spring的远程调用完全相同,WebService的本质也就是远程调用,只不过Spring和WebService的实现原理不相同而已。比较WebService和Spring的远程调用:
1.Spring远程调用在网络上传输的是“串行化对象”,而WebService在网络上传输的是XML字符串。
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。
二、名词解释
1.WSDL
全名为WebService Description Language ,翻译过来就是Web服务描述语言。它使用XML描述服务的地址,服务提供的方法以及参数列表、返回值类型等,实际上就是一个Web服务的说明书,比如webxml.com.cn网站提供了天气预报查询的服务,对应的WSDL就是:http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl
2.SOAP
全名为Simple Object Access Protocol,翻译过来就是简单对象访问协议,SOAP是一种XML语言的协议,用于在网络上传输数据。
SOAP=XML+HTTP
SOAP是基于Http协议的,SOAP的组成:Envelope,这是必须的部分,以XML根元素的形式出现;Headers,可选;Body,必须的部分,包含要执行的服务器上的方法和发送到服务器上的数据。
三、在Java项目中发布第一个WebService服务
package com.kdyzm.ws; import javax.jws.WebService;
import javax.xml.ws.Endpoint; @WebService
public class MyWsServer {
public String calculate(int input){
return input*input+"";
}
public static void main(String[] args) {
Endpoint.publish("http://localhost:9090/ws", new MyWsServer());
System.out.println("server ready ......");
}
}
OK,一个最简单的WebService服务就发布了。
对以上的代码的说明:在Java中,使用EndPoint类发布服务,使用该类发布服务的方法是publish方法,该方法由两个参数,一个参数是发布服务的地址,另外一个参数是提供服务的类;当执行到publish方法的时候,程序会新开一个线程专门用于提供服务,主线程会继续执行下去,所以下面的打印的代码会不受影响的执行。
另外,提供服务的类至少应当提供一个非静态方法否则服务启动不起来。
如何查看wsdl?在浏览器上输入http://localhost:9090/ws?wsdl,回车即可查看wsdl内容:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is
JAX-WS RI 2.1.6 in JDK 6. -->
<!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is
JAX-WS RI 2.1.6 in JDK 6. -->
<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://ws.kdyzm.com/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://ws.kdyzm.com/"
name="MyWsServerService">
<types>
<xsd:schema>
<xsd:import namespace="http://ws.kdyzm.com/"
schemaLocation="http://localhost:9090/ws?xsd=1"></xsd:import>
</xsd:schema>
</types>
<message name="calculate">
<part name="parameters" element="tns:calculate"></part>
</message>
<message name="calculateResponse">
<part name="parameters" element="tns:calculateResponse"></part>
</message>
<portType name="MyWsServer">
<operation name="calculate">
<input message="tns:calculate"></input>
<output message="tns:calculateResponse"></output>
</operation>
</portType>
<binding name="MyWsServerPortBinding" type="tns:MyWsServer">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document"></soap:binding>
<operation name="calculate">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal"></soap:body>
</input>
<output>
<soap:body use="literal"></soap:body>
</output>
</operation>
</binding>
<service name="MyWsServerService">
<port name="MyWsServerPort" binding="tns:MyWsServerPortBinding">
<soap:address location="http://localhost:9090/ws"></soap:address>
</port>
</service>
</definitions>
四、使用wsimport命令生成本地调用代码。
如果能力足够高的话,直接阅读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文档。
客户端的测试代码:
package com.kdyzm.test; import com.kdyzm.ws.MyWsServer;
import com.kdyzm.ws.MyWsServerService; public class Main {
public static void main(String[] args) {
MyWsServerService myWsServerService=new MyWsServerService();
MyWsServer myWsServer=myWsServerService.getMyWsServerPort();
String result=myWsServer.calculate(2);
System.out.println(result);
}
}
控制台输出结果是4(客户端)。
六、使用Web Service Exployer工具查看请求信息和相应信息。
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协议的规范的。
【Java EE 学习 80 上】【WebService】的更多相关文章
- 【Java EE 学习 74 上】【数据采集系统第六天】【使用Jfreechart的统计图实现】【Jfreechart的基本使用方法】
之前已经实现了数据的采集,现在已经有了基本的数据,下一步就需要使用这些数据实现统计图的绘制了.这里使用Jfreechart实现这些统计图的绘制.首先看一下Jfreechart的基本用法,只有知道了它的 ...
- 【Java EE 学习 25 上】【网上图书商城项目实战】
一.概述 1.使用的jdk版本:1.6 2.java EE版本:1.6 3.指导老师:传智播客 王建 二.小项目已经实现的功能 普通用户: 1.登陆 2.注册 3.购物 4.浏览 管理员用户(全部管理 ...
- 【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】
不考虑第三方框架,如果只使用JDK提供的API,那么可以使用三种方式调用WebService服务:另外还可以使用Ajax调用WebService服务. 预备工作:开启WebService服务,使用jd ...
- 【Java EE 学习 67 上】【OA项目练习】【JBPM工作流的使用】
OA项目中有极大可能性使用到JBPM框架解决流程控制问题,比如请假流程.报销流程等等. JBPM:JBoss Business Process Management,翻译过来就是业务流程管理.实际上就 ...
- 【Java EE 学习 83 上】【SpringMVC】【基本使用方法】
一.SpringMVC框架概述 什么是SpringMVC?SpringMVC是一个和Struts2差不多的东西,他们的作用和性质几乎是相同的,甚至开发效率上也差不多,但是在运行效率上SpringMVC ...
- 【Java EE 学习 82 上】【MAVEN基本安装和使用方法】
一.Maven概述 1.什么是Maven? Maven中文意思是"行家"."专家",它是一种跨平台的项目管理工具. 2.Maven有什么作用? Maven能够实 ...
- 【Java EE 学习 79 上】【mybatis 基本使用方法】
一.简介 mybatis类似于hibernate,都是简化对数据库操作的框架,但是和hibernate不同的是,mybatis更加灵活,整体来说框架更小,这体现在它需要我们手写SQL语句,而hiber ...
- 【Java EE 学习 78 上】【数据采集系统第十天】【Service使用Spring缓存模块】
一.需求分析 调查问卷中或许每一个单击动作都会引发大量的数据库访问,特别是在参与调查的过程中,只是单击“上一页”或者“下一页”的按钮就会引发大量的查询,必须对这种问题进行优化才行.使用缓存策略进行查询 ...
- 【Java EE 学习 77 上】【数据采集系统第九天】【通过AOP实现日志管理】【通过Spring石英调度动态生成日志表】【日志分表和查询】
一.需求分析 日志数据在很多行业中都是非常敏感的数据,它们不能删除只能保存和查看,这样日志表就会越来越大,我们不可能永远让它无限制的增长下去,必须采取一种手段将数据分散开来.假设现在整个数据库需要保存 ...
随机推荐
- 做web开发和测试,修改hosts指定某个域名访问某个特定的IP后,如何使hosts立即生效的方法
本文转自SUN'S BLOG,原文地址:http://whosmall.com/post/143 hosts的配置方法: 在windows系统中,找到C:\windows\system32\drive ...
- react 犯错
1. import a from './xx' 一定要有 ./ 2. export default const x={} 错 改为 const x={}; export default x; 也 ...
- Angular datetime format
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javas ...
- Xcode6新特性(1)-删除Main.storyboard
当新建完一个空项目的时候,Xcode会自动创建一个Main.storyboard的空文件,如果不需要,可以将其删除.但是如果删除,再次运行程序,程序会报错,提示找不到Main.storyboard文件 ...
- Nginx设置线程数为整机内核数的俩倍!
Nginx设置线程数为整机内核数的俩倍!
- 【ueditor】api方法
//让其选中文本高亮 editor.selection.getRange().select(); //高亮后,才能获取到选中文本,当选中字失去焦点的情况下是获取不到的选中文本的 var text = ...
- Abp集成Swagger的最佳实践
1.在项目中添加nuget包 Abp.Web.Api.SwaggerTool 2.在项目Abp模块的DependsOn添加AbpWebApiSwaggerToolModule Run It,启动项目, ...
- python模块简介
模块:用代码实现了某个功能的代码集合,功能模块化,节省时间,提高效率 一.模块的导入 导入模块,其实就是告诉python解释器去解释相应的.py文件 • 导入.py文件,解释器解释该.py文件 • 倒 ...
- CSS 常用基本功能整理
1.文字访问特权 点击前.点击时.点击后.下划线.跳转. <!DOCTYPE html> <html> <head> <meta charset=" ...
- CentOS6.3 重启后/etc/resolv.conf 被还原解决办法(转)
今天一台服务器上不了网,设置了nameserver,重启后/etc/resolv.conf文件就被自动还原了,最后发现是被Network Manager修改了.解决方法:停止Network Manag ...