转载于: http://blog.csdn.net/bayougeng/archive/2009/07/27/4384260.aspx
本文是在公司做Web Service技术研究时候的文档。部分资料来源于网络,部分是我自己的体会。贴出来给Web Service的初学者,希望能加快你们学习的步伐。
第一部分:主要介绍Web Service以及相关的协议、术语的概念以及Web Service的特点。
Web Service:
是一种革命性的分布式计算技术。它使用基于XML的消息处理作为基本的数据通讯方式。消除使用不同组件模型、操作系统和编程语言的系统之间存在的差异,使异类系统能够作为计算网络的一部分协同运行。开发人员可以使用像过去创建分布式应用程序时使用组件的方式,创建由各种来源的Web服务组合在一起的应用程序。由于Web服务是建立在一些通用协议的基础上,如HTTP,SOAP,XML,WSDL,UDDI等,这些协议在涉及到操作系统、对象模型和编程语言的选择时,没有任何倾向。因此Web服务将会有很强的生命力。
SOAP:
是“Simple Object Access Protocol”的缩写,SOAP是消息传递的协议,它规定了Web Services之间是怎样传递信息的。简单的说,SOAP规定了:
1. 传递信息的格式为XML。这就使Web Services能够在任何平台上,用任何语言进行实现。
2. 远程对象方法调用的格式。规定了怎样表示被调用对象以及调用的方法名称和参数类型等。
3. 参数类型和XML格式之间的映射。这是因为,被调用的方法有时候需要传递一个复杂的参数,例如,一个Person对象。怎样用XML来表示一个对象参数,也是SOAP所定义的范围。
WSDL:
是“Web Services Description Language”的缩写。WSDL是Web Services的定义语言。当实现了某种服务的时候(如:股票查询服务),为了让别的程序调用,必须告诉大家服务接口。例如:服务名称,服务所在的机器名称,监听端口号,传递参数的类型,个数和顺序,返回结果的类型等等。这样别的应用程序才能调用该服务。WSDL协议就是规定了有关Web Services描述的标准。
UDDI:
是“Universal Description, Discovery,and Integration”的缩写。简单说,UDDI用于集中存放和查找WSDL描述文件,起着目录服务器的作用。
XML:
(eXtensible Markup Language,可扩展标记语言)是Internet上数据表示和数据交换的新标准。它是ISO(International Organization for Standardization,国际标准化组织)的SGML(Standard for General Markup Language,通用标记语言标准)的一个简化子集。XML关注信息本身,是Web上表示结构化信息的一种标准文本格式。与传统的注重页面信息显示的 HTML(Hypertext Markup Language,超文本链接标示语言)相比,关注于内容的XML具有以下诸多优点:良好的可扩展性,语言简单有效,可自行定义标记;内容与形式的分离,主要刻画数据内容,不考虑显示效果;有严格的语法要求,便于分析统一和与数据库信息转换;便于传输,为纯文本形式,可通过Http协议直接传输,可跨越防火墙;等等。
DTD:
(Document Type Definition,文档类型定义)DTD 是一套关于标记符的语法规则。它是XML1.0版规格得一部分,是XML文件的验证机制,属于XML文件组成的一部分。DTD 是一种保证XML文档格式正确的有效方法,可以通过比较XML文档和DTD文件来看文档是否符合规范,元素和标签使用是否正确。DTD文档包含:元素的定义规则,元素间关系的定义规则,元素可使用的属性,可使用的实体或符号规则。XML文件提供应用程序一个数据交换的格式,DTD正是让XML文件能够成为数据交换的标准,因为不同的公司只需定义好标准的DTD,各公司都能够依照DTD建立XML文件,并且进行验证,如此就可以轻易的建立标准和交换数据,这样满足了网络共享和数据交互。DTD文件是一个ASCII的文本文件,后缀名为.dtd。
WS-I:
WS-I全称为:网络服务标准组织。WS-I Basic Profile是为了开发可相互连接的Web服务而推出的指南,介绍了如何配合使用SOAP、WSDL、UDDI、XML、XML Schema等Web服务的核心标准。
Axis:
Axis(Apache extensible Interaction system)是Apache项目组织的一个开源项目。前身是Apache SOAP。Axis总体上是一个SOAP引擎,但又不仅仅是个引擎,它还:
1)是一个简单的独立的服务器
2)是一个可插入到servlet引擎(如Tomcat)中的服务
3)可扩展的支持WSDL
4)能根据WSDL产生JAVA文件/类
5)包括一些例子程序6)包括一个可以监控TCP/IP包的工具
Axis支持三种web service的部署和开发,分别为:
1、Dynamic Invocation Interface ( DII)
2、Dynamic Proxy方式
3、Stubs方式
对于前两种Web Service的发布基本一样,客户端的访问也很类似,第一种发布就是直接将.java后缀改为.jws,并将生成的.class文件拷贝到WEB-INF/jwsclasses下面。
第三种是目前比较流行的方式。也是Force.com Web Service采用的方式。stub意思是树桩,意味着服务端和客户端都是通过桩的形式来完成访问的,即在服务端将java转换成wsdl,在客户端将wsdl装换成java,这样就实现了良好的桩的分离。
--------------------------------------------------------------------------------
第二部分:主要介绍使用Axis开发Web Service使用的工具、工具版本以及配置步骤。
工具/开发包 版本
JDK 1.6
eclipse 3.2.2
Axis 1.4
Tomcat 5.5
tomcatPluginV31 -
1.安装jdk1.6。
2.释放eclipse的压缩包。我释放的路径是:D:/Program Files。
3.释放Tomcat压缩包。我释放的路径是:D:/Server。
4.释放Axis压缩包。我的释放路径是:D:/Server。
5.安装eclipse下开发tomcat的plugin,这里不细述。
--------------------------------------------------------------------------------
第三部分:主要介绍如何构造简单的Web Service服务。
1.通过最基本的DII方式式构建Web Service。
1.1.在eclipse中建立新的tomcat工程。名字:AxisTest
1.2.将axis-1_4/webapps/axis中几个必须的文件拷贝到你的AxisTest工程文件下。其一是WEB-INF/lib下的所有文件,其二是WEB-INF下面的web.xml文件。
1.3.将三个jar导入工程的WEB-INF/lib下。分别是:tools.jar,activation.jar,mail.jar(这三个是常用的jar,应该很熟悉吧?)。
1.4.在源文件目录下,建立文件MyService1.java。内容如下:
view plaincopy to clipboardprint?
public class MyService1 {
public String showWelcomeMessage(String userName){
return "Hello " + userName + ",you are welcome to TSR.";
}
}
public class MyService1 {
public String showWelcomeMessage(String userName){
return "Hello " + userName + ",you are welcome to TSR.";
}
}
1.5.将这MyService1.java移动到AxisTest根目录下。并修改扩展名为.jws。
1.6.用浏览器访问下面的地址:http://localhost:8080/AxisTest/MyService1.jws,如果配置正确,可以得到下面的画面:
点击这个link,服务器端会编译MyService1.jws文件,在WEB-INF/jwsClasses目录中生成.class文件。
MyService1这个Web Service就成功发布了。
结果页面看到的就是这个Web Service的WSDL文件。如下图:
1.7.接下来我们写一个java程序来调用这个Web Service。代码如下:
view plaincopy to clipboardprint?
package cn.com.ctsr.axis.runable;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.ServiceException;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
public class TestService {
/**
* @param args
*/
public static void main(String[] args) throws ServiceException,
MalformedURLException, RemoteException {
// TODO Auto-generated method stub
String endpoint = "http://localhost:8080/AxisTest/MyService1.jws";
String name = "YangBo";
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpoint));
call.addParameter("userName", XMLType.XSD_STRING, ParameterMode.IN);
call.setOperationName("showWelcomeMessage");
call.setReturnType(XMLType.XSD_STRING);
String ret = (String) call.invoke(new Object[] { name });
System.out.println("The result:" + ret);
}
}
package cn.com.ctsr.axis.runable;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.ServiceException;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
public class TestService {
/**
* @param args
*/
public static void main(String[] args) throws ServiceException,
MalformedURLException, RemoteException {
// TODO Auto-generated method stub
String endpoint = "http://localhost:8080/AxisTest/MyService1.jws";
String name = "YangBo";
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpoint));
call.addParameter("userName", XMLType.XSD_STRING, ParameterMode.IN);
call.setOperationName("showWelcomeMessage");
call.setReturnType(XMLType.XSD_STRING);
String ret = (String) call.invoke(new Object[] { name });
System.out.println("The result:" + ret);
}
}
运行程序得到如下的结果:.
The result:Hello YangBo,you are welcome to TSR.
注意,这种方式暂时用不上WSDL。
到这里,一个最简单的Web Service就构造成功了。
2.下面介绍另外一种方式,也是目前最流行的方式:Stubs方式。
2.1.建立服务器端运行的Web Service程序。我的服务程序如下:
view plaincopy to clipboardprint?
package cn.com.ctsr.axistest.server;
import jp.co.sei.is.lib21.SeiCalc;
public class MyService2 {
public String calculate(String expression){
return SeiCalc.eval(expression);
}
}
package cn.com.ctsr.axistest.server;
import jp.co.sei.is.lib21.SeiCalc;
public class MyService2 {
public String calculate(String expression){
return SeiCalc.eval(expression);
}
}
*这里使用了的jp.co.sei.is.lib21.SeiCalc#eval请自行找方法替代。因为大家可能没有这个开发包。这个方法是做一个计算。参数是一个计算式,返回这个计算式的值。比如,参数:2*3,返回值:5。
2.2.在工程目录下,建立文件夹:java2wsdl。并做成新的文件:build.xml。这个文件用来根据Web Service类生成wsdl文件。内容如下:
view plaincopy to clipboardprint?
<?xml version="1.0"?>
<project name="Generate WSDL from JavaBeans as Web Services" default="j2w-all" basedir=".">
<property name="build.dir" value="../WEB-INF/classes"/>
<path id="classpath.id">
<fileset dir="../WEB-INF/lib">
<include name="*.jar"/>
</fileset>
<pathelement location="${build.dir}"/>
</path>
<taskdef name="axis-java2wsdl" classname="org.apache.axis.tools.ant.wsdl.Java2WsdlAntTask"
loaderref="axis" >
<classpath refid="classpath.id"/>
</taskdef>
<target name="j2w-all">
<antcall target="j2w-JavaBeanWS"/>
</target>
<target name="j2w-JavaBeanWS">
<axis-java2wsdl
classname="cn.com.ctsr.axistest.server.MyService2"
classpath="${build.dir}"
methods="calculate"
output="MyService2.wsdl"
location="http://172.28.18.19:8080/AxisTest/services/MyService2"
namespace="http://172.28.18.19:8080/AxisTest/services/MyService2"
namespaceImpl="http://172.28.18.19:8080/AxisTest/services/MyService2">
</axis-java2wsdl>
</target>
</project>
<?xml version="1.0"?>
<project name="Generate WSDL from JavaBeans as Web Services" default="j2w-all" basedir=".">
<property name="build.dir" value="../WEB-INF/classes"/>
<path id="classpath.id">
<fileset dir="../WEB-INF/lib">
<include name="*.jar"/>
</fileset>
<pathelement location="${build.dir}"/>
</path>
<taskdef name="axis-java2wsdl" classname="org.apache.axis.tools.ant.wsdl.Java2WsdlAntTask"
loaderref="axis" >
<classpath refid="classpath.id"/>
</taskdef>
<target name="j2w-all">
<antcall target="j2w-JavaBeanWS"/>
</target>
<target name="j2w-JavaBeanWS">
<axis-java2wsdl
classname="cn.com.ctsr.axistest.server.MyService2"
classpath="${build.dir}"
methods="calculate"
output="MyService2.wsdl"
location="http://172.28.18.19:8080/AxisTest/services/MyService2"
namespace="http://172.28.18.19:8080/AxisTest/services/MyService2"
namespaceImpl="http://172.28.18.19:8080/AxisTest/services/MyService2">
</axis-java2wsdl>
</target>
</project>
2.3.在工程WEB-INF目录下建立新文件:server-config.wsdd。这个文件用来配置服务器所有的Web Service。内容如下:
view plaincopy to clipboardprint?
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<globalConfiguration>
<parameter name="adminPassword" value="admin"/>
<parameter name="attachments.Directory" value="C:/eclipse/workspace/bookstore/WEB-INF/attachments"/>
<parameter name="attachments.implementation" value="org.apache.axis.attachments.AttachmentsImpl"/>
<parameter name="sendXsiTypes" value="true"/>
<parameter name="sendMultiRefs" value="true"/>
<parameter name="sendXMLDeclaration" value="true"/>
<parameter name="axis.sendMinimizedElements" value="true"/>
<requestFlow>
<handler type="java:org.apache.axis.handlers.JWSHandler">
<parameter name="scope" value="session"/>
</handler>
<handler type="java:org.apache.axis.handlers.JWSHandler">
<parameter name="scope" value="request"/>
<parameter name="extension" value=".jwr"/>
</handler>
</requestFlow>
</globalConfiguration>
<handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder"/>
<handler name="Authenticate" type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/>
<handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper"/>
<service name="Version" provider="java:RPC">
<parameter name="allowedMethods" value="getVersion"/>
<parameter name="className" value="org.apache.axis.Version"/>
</service>
<service name="AdminService" provider="java:MSG">
<parameter name="allowedMethods" value="AdminService"/>
<parameter name="enableRemoteAdmin" value="false"/>
<parameter name="className" value="org.apache.axis.utils.Admin"/>
<namespace>http://xml.apache.org/axis/wsdd/</namespace>
</service>
<service name="MyService2" provider="java:RPC">
<parameter name="className" value="cn.com.ctsr.axistest.server.MyService2"/>
<parameter name="allowedMethods" value="*"/>
</service>
<transport name="local">
<responseFlow>
<handler type="LocalResponder"/>
</responseFlow>
</transport>
<transport name="http">
<requestFlow>
<handler type="URLMapper"/>
<handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>
</requestFlow>
</transport>
</deployment>
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<globalConfiguration>
<parameter name="adminPassword" value="admin"/>
<parameter name="attachments.Directory" value="C:/eclipse/workspace/bookstore/WEB-INF/attachments"/>
<parameter name="attachments.implementation" value="org.apache.axis.attachments.AttachmentsImpl"/>
<parameter name="sendXsiTypes" value="true"/>
<parameter name="sendMultiRefs" value="true"/>
<parameter name="sendXMLDeclaration" value="true"/>
<parameter name="axis.sendMinimizedElements" value="true"/>
<requestFlow>
<handler type="java:org.apache.axis.handlers.JWSHandler">
<parameter name="scope" value="session"/>
</handler>
<handler type="java:org.apache.axis.handlers.JWSHandler">
<parameter name="scope" value="request"/>
<parameter name="extension" value=".jwr"/>
</handler>
</requestFlow>
</globalConfiguration>
<handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder"/>
<handler name="Authenticate" type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/>
<handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper"/>
<service name="Version" provider="java:RPC">
<parameter name="allowedMethods" value="getVersion"/>
<parameter name="className" value="org.apache.axis.Version"/>
</service>
<service name="AdminService" provider="java:MSG">
<parameter name="allowedMethods" value="AdminService"/>
<parameter name="enableRemoteAdmin" value="false"/>
<parameter name="className" value="org.apache.axis.utils.Admin"/>
<namespace>http://xml.apache.org/axis/wsdd/</namespace>
</service>
<service name="MyService2" provider="java:RPC">
<parameter name="className" value="cn.com.ctsr.axistest.server.MyService2"/>
<parameter name="allowedMethods" value="*"/>
</service>
<transport name="local">
<responseFlow>
<handler type="LocalResponder"/>
</responseFlow>
</transport>
<transport name="http">
<requestFlow>
<handler type="URLMapper"/>
<handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>
</requestFlow>
</transport>
</deployment>
*请注意,<service name="MyService2" provider="java:RPC">就是我们自己的Web Service的配置。另外还有两个Web Service是Axis自带的。其他地方的配置请参考相关文档。
2.4.右键点击java2wsdl/build.xml,选择run as -> Ant Build。此操作成功执行后,会在该文件夹下生成MyService2.wsdl文件。这个文件就是我们自定义的Web Service:MyService2的wsdl文件。
2.5.启动tomcat,访问网址:http://172.28.18.19:8080/AxisTest/services。正确的结果如下图:
服务器端的工作到这里就完成了,下面我们在客户端做一个程序来调用这个Web Service。
2.6.在工程根目录下,新建一个新的source folder,名称:wsdl2java。在这个目录下建立新的文件:build.xml。此文件用来从服务器端获得指定Web Service的wsdl文件,并转换成客户端使用所需要的java类。内容如下:
view plaincopy to clipboardprint?
<?xml version="1.0" encoding="UTF-8"?>
<project name="wsclient" default="all" basedir=".">
<property name="axis.home" location="D:/Server/axis-1_4"/>
<property name="options.output" location="../wsdl2java"/>
<path id="axis.classpath">
<fileset dir="../WEB-INF/lib">
<include name="*.jar"/>
</fileset>
</path>
<taskdef resource="axis-tasks.properties" classpathref="axis.classpath" />
<target name="-WSDL2Axis">
<mkdir dir="${options.output}"/>
<axis-wsdl2java
output="${options.output}"
debug="true"
url="http://172.28.18.19:8080/AxisTest/java2wsdl/MyService2.wsdl"
deployscope="Request"
testcase="false"
noimports="false"
verbose="true"/>
</target>
<target name="all">
<antcall target="MyService2"/>
</target>
<target name="MyService2">
<antcall target="-WSDL2Axis">
<param name="options.WSDL-URI" location="http://172.28.18.19:8080/AxisTest/java2wsdl/MyService2.wsdl"/>
</antcall>
</target>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project name="wsclient" default="all" basedir=".">
<property name="axis.home" location="D:/Server/axis-1_4"/>
<property name="options.output" location="../wsdl2java"/>
<path id="axis.classpath">
<fileset dir="../WEB-INF/lib">
<include name="*.jar"/>
</fileset>
</path>
<taskdef resource="axis-tasks.properties" classpathref="axis.classpath" />
<target name="-WSDL2Axis">
<mkdir dir="${options.output}"/>
<axis-wsdl2java
output="${options.output}"
debug="true"
url="http://172.28.18.19:8080/AxisTest/java2wsdl/MyService2.wsdl"
deployscope="Request"
testcase="false"
noimports="false"
verbose="true"/>
</target>
<target name="all">
<antcall target="MyService2"/>
</target>
<target name="MyService2">
<antcall target="-WSDL2Axis">
<param name="options.WSDL-URI" location="http://172.28.18.19:8080/AxisTest/java2wsdl/MyService2.wsdl"/>
</antcall>
</target>
</project>
*注意url="http://172.28.18.19:8080/AxisTest/java2wsdl/MyService2.wsdl"这个部分。如果想使用本地文件目录中的wsdl文件,而不是使用web上的wsdl文件,需要这样写:
url="file:///d:/Program Files/eclipse322/workspace/AxisTest/java2wsdl/MyService2.wsdl"
"file"后面有三个斜线,千万别错了。
2.7.右键点击wsdl2java/build.xml,选择run as -> Ant Build。如果配置正确,运行后会在此目录下生成一个包。包中包括4个java文件。
2.8.新建一个java文件。用来调用刚刚Web Service。我已经写好了一个,代码如下:
view plaincopy to clipboardprint?
package cn.com.ctsr.axistest.client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import jp.co.sei.is.lib21.SeiUtil;
import _19._18._28._172.AxisTest.services.MyService2.MyService2;
import _19._18._28._172.AxisTest.services.MyService2.MyService2ServiceLocator;
public class TestService2 {
/**
* @param args
*/
public static void main(String[] args){
// TODO Auto-generated method stub
MyService2ServiceLocator Service= new MyService2ServiceLocator();
MyService2 port= null;
BufferedReader p_in = new BufferedReader(
new InputStreamReader(System.in));
String p_expression = null;
try{
port = Service.getMyService2();
while(!SeiUtil.isEmpty(p_expression = p_in.readLine())){
String response=port.calculate(p_expression);
System.out.println(p_expression + " = " + response);
}
}catch(Exception e){
e.printStackTrace(System.err);
}
System.out.print("Bye!");
}
}
package cn.com.ctsr.axistest.client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import jp.co.sei.is.lib21.SeiUtil;
import _19._18._28._172.AxisTest.services.MyService2.MyService2;
import _19._18._28._172.AxisTest.services.MyService2.MyService2ServiceLocator;
public class TestService2 {
/**
* @param args
*/
public static void main(String[] args){
// TODO Auto-generated method stub
MyService2ServiceLocator Service= new MyService2ServiceLocator();
MyService2 port= null;
BufferedReader p_in = new BufferedReader(
new InputStreamReader(System.in));
String p_expression = null;
try{
port = Service.getMyService2();
while(!SeiUtil.isEmpty(p_expression = p_in.readLine())){
String response=port.calculate(p_expression);
System.out.println(p_expression + " = " + response);
}
}catch(Exception e){
e.printStackTrace(System.err);
}
System.out.print("Bye!");
}
}
*注意_19._18._28._172.AxisTest.services.MyService2.MyService2和_19._18._28._172.AxisTest.services.MyService2.MyService2ServiceLocator就是2.7最终生成的class。
2.9.运行2.8中做成的客户端程序,得到类似下面的运行结果:
Stubs方式的Web Service就完成了。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/bayougeng/archive/2009/07/27/4384260.aspx