您的位置:首页 > 其它

快速实践JAX-WS 2.0

2006-11-07 13:39 337 查看
本文根据SUN官方网站EnterpriseJavaTechnologiesTechTips栏目上的一篇文章改写的,所有过程均调试通过。
一.前言
SOA思想的核心在于"S",凡是从服务的角度去看待系统功能,并且构建和实现应用,都可以认为是SOA的某种实现形式。下面一段要说的是:SOA技术的核心在于"O"--只有做到Service-Orientation的技术,才能真正称为SOA技术。
怎样才能算作Service-Orientation?我们再以OO进行类比:VB之所以被称为基于对象(Object-Based)而不是面向对象(Object-Oriented)的语言,是因为VB的运行时结构不具有VMT等基本构造,语法上也不支持私有成员,继承等基础特性,两者结合,就造成无法支持封装,继承,多态等面向对象的关键技术。一句话,VB不是围绕“对象”这个核心概念设计的语言。对于SOA技术,它也可以从这个角度划分两个层次:一个是SOA的“运行时”相关结构标准,例如SOAP,WSDL,WS-*等,相当于OO中的对象内部结构,VMT构造等。另外一个则是语言和工具层面的支持,例如基于元数据的服务描述,支持WebService的类库,Proxy生成工具等,相当于OO语言中提供的基本OO语法,类库,编绎器等。这两个层次共同构成SOA体系结构中的要素,让人们能够围绕“服务”这个核心概念进行系统开发和应用。因此,一种技术架构,平台或产品要称作SOA,应当同时具备这一两方面的特征。
所以,下面将要讨论的JAX-WS技术,从上面的观点来看,也就是SOA技术的第二个层次,即语言和工具层面的支持--Java,例如基于元数据的服务描述,支持WebService的类库,Proxy生成工具等.
JavaAPIforXMLWebServices(JAX-WS)2.0,是JavaEE5平台的一个重要的部分。作为JavaAPIforXML-baseedRPC1.1(JAX-RPC)的后续版本,在JAX-RPC1.1中,开发人员需要写一个接口类ServiceEndpointInterface(SEI),在JAX-WS2.0中,开发人员一上来就可以直接写自己的实现类.通过使用annotations,自动生成SEI和其他一些文件.这样有助于开发人员专注于自己想开发的部分,而不必要地分散精力去维护其他的一些附属文件.
.快速实践JAX-WS2.0
下面通过一个两个数相加的简单例子来看看,JAX-WS2.0API的应用过程.程序是一个独立的客户端传给服务端两个整数,经过服务端处理后,将结果返回到客户端并打印出来.
.环境配置.
1.JDK5.0orhigher
下载:'target='_blank'>http://java.sun.com/javase/downloads/index.jsp2.JavaEE5.0AppServer.
这个例子是基于JavaEE5的一个开源实现项目GlassFish。https://glassfish.dev.java.net/public/downloadsindex.html
本例子所需的基本代码的压缩包可以通过这个链接下载。里面包括了这个例子需要的代码,构建脚本和一个build文件。
环境变量的配置:
·
GLASSFISH_HOME.
这个应该指向你安装GlassFish的目录(比如,我系统上的是:J:/Sun/AppServer)

·
ANT_HOME.
这个应该指向ant所安装的目录。在你下载GlassFishbundle时Ant已经被包含在里面了。(对于Windows系统,它是在lib/ant子目录)。不过你也可以从
ApacheAntProjectpage.下载Ant。对于这个例子需要Apacheant1.6.5
·
J***A_HOME.
这个应该指向你系统上安装的JDK5.0(orhigher)的目录。
同时,把ant的bin目录添加到Path环境变量中去(J:/apache-ant-1.6.5/bin),当然了JDK的bin目录也加进去了。

然后下载例子的代码包并且解压。根文件夹是jaxws-techtip。




endpoint/
目录下有一个文件Calculator.java

client/
目录下有一个文件JAXWSClient.java

二.编写构建服务端

随着第一步环境配置的完全,现在该开始构建一个web服务了。在这个例子里,web服务是从一个Java类来开发的。为了构建这个web服务:
1.写一个端点实现类(endpointimplementationclass)。
2.编绎这个端点实现类。
3.有选择的产生对web服务的运行必须具备的那些可移植的制品。
4.把web服务打包成一个WAR文件并且在AppServer中部署它。
1编写实现类.
进到
endpoint/
目录下,可以看到里面有一个文件Calculator.java.它是一个端点实现类,具备有对两个整数进行相加的简单服务。

JAX-WS2.0大量地依赖注释(annotations)的使用,它是AMetadataFacilityfortheJavaProgrammingLanguage(JSR175)描述的规范和WebServicesMetadatafortheJavaPlatform(JSR181)描述的规范。


packageendpoint;




importjavax.jws.WebService;


importjavax.jws.WebMethod;




@WebService(


name="Calculator",


serviceName="CalculatorService",


targetNamespace="http://techtip.com/jaxws/sample"


)




publicclassCalculator...{




publicCalculator()...{}




@WebMethod(operationName="add",action="urn:Add")




publicintadd(inti,intj)...{


intk=i+j;


System.out.println(i+"+"+j+"="+k);





returnk;


}


}




研究上面的实现类
Calculator
,注意到类里的两个注释的使用
@WebService
@WebMethod。一个正确的端点实现类必须包含有一个@WebService注释。这个注释标注这个类将作为一个web服务对外开放。@WebService的name属性表明了web服务描述语言(WSDL)里的端口类型(
portType
)(在这个例子里是”Calculator”)。而
serviceName="CalculatorService"对应的是一个WSDL里的服务元素(service)。targetNamespace属性为WSDL说明了XML的命名空间。所有的这些属性都是可选的。对于这些属性的默认值是什么,请参考WebServicesMetadatafortheJavaPlatform规范,JSR181。
再来看看另外一个重要的注释[code]@WebMethod,被它注释过的方法说明将它以一个
[/code]
[code]web服务的方法暴露出来,被其他应用来调用。
@WebMethod注释里的operationName[/code]
声明了WSDL里的一个元素WSDLoperation(在这个例子里,”add”),另外一

个属性action=("[code]urn:Add
"),它为WSDL还有一些从这个web服务操作(webserviceoperation)生[/code]
成的元素声明了一个命名空间。这两个属性都是可选的。如果你没有列出来的

话,WSDL操作(operation)的值将会默认为方法名,还有action值也会默认为

服务的[code]targetNamespace。
[/code]
[code]
2
编绎实现类
[/code]
写完了上面的实现类之后,你需要编绎它。点击开始->程序->SunMicrosystems->“StartDefaultServer”启动应用服务器或者通过在DOS窗口下敲下面的命令来启动它:<GF_install_dir>/bin/asadminstart-domaindomain1,其中GF_install_dir是你安装GlassFish的目录,也就是说先到<GF_install_dir>/bin目录下,然后用命令asadminstart-domaindomain1来启动应用服务器。现在将目录转到jaxws-techtip文件夹下,运行下面的ant命令,也就是执行第一个任务complie:
antcompile
执行这个命令就相当于执行以下的javac命令(都是在同一行):
javac-classpath$GLASSFISH_HOME/lib/javaee.jar-d
./build/classes/service/endpoint/Calculator.java

3web服务的执行产生可移植的制品
这一步是可选的。如果在这个web服务的部署期间,他们没有和一个可配置的服务单元绑定,GlassFish的部署工具能够自动地产生这些制品。然而对于刚刚接触JAX-WS来说,对于弄清楚整个编程模式来说,通过手动产生地会话会更有帮助,即运行下面的命令:
antgenerate-runtime-artifacts
这个任务将会在jaxws-techtip目录下生成build/generated目录,并且运行了下面的wsgen命令(都是在同一行):
$GLASSFISH_HOME/bin/wsgen-cp./build/classes/service-keep-d./build/classes/service–r./build/generated-wsdlendpoint.Calculator
一个WSDL文件(CalculatorService.wsdl)在build/generated目录下生成了,还在同个目录下生成了另外一个schema文件(CalculatorService_schema1.xsd),它为CalculatorService.wsdl定义了schema。
JavaBean技术组件(JavaBeans)在编组(marshaling,java->XML)的方法调用,响应,还有service-specific异常中起了很大的作用。这些类将会在web服务在一个应用服务器中运行的时候被使用。JavaBean类在jaxws-techtip目录下的/build/classes/service/endpoint/jaxws目录被生成了,这些类是:
Add.java
Add.class
AddResponse.java
AddResponse.class

4打包并部署WAR文件
接下来你需要做的工作就是对服务进行打包和部署。为了做这个,你需要在一个部署描述符中详细说明这个服务。Web服务可以绑定成servlet的形式或者无状态的sessionbean形式打包成WebArchive(WAR)文件。在这个例子里把它绑定为一个servlet。
为了把这个服务打包成一个WAR文件,定位到jaxws-techtip文件夹,并且在DOS窗口上运行下面的命令:
antpkg-war
对于这个war文件的结构,我们可以到build.xml文件里看看pkg-war目标:
<targetname="pkg-war"depends="init-common">
<mkdirdir="${assemble.dir}"/>
<echomessage="mybuildclassesdiris:${build.classes.dir}"level="verbose"/>
<mkdirdir="${build.classes.dir}/tmp"/>
<mkdirdir="${build.classes.dir}/tmp/WEB-INF"/>
<mkdirdir="${build.classes.dir}/tmp/WEB-INF/classes"/>
<mkdirdir="${build.classes.dir}/tmp/WEB-INF/wsdl"/>
<copyfile="${web.xml}"
tofile="${build.classes.dir}/tmp/WEB-INF/web.xml"failonerror="false"/>
<copytodir="${build.classes.dir}/tmp/WEB-INF/classes">
<filesetdir="${build.classes.dir}/service">
<includename="**/*.class"/>
<includename="**/${handler.name}"/>
</fileset>
</copy>
<copytodir="${build.classes.dir}/tmp/WEB-INF/wsdl">
<filesetdir="${build.generated.dir}">
<includename="**/*.*"/>
</fileset>
</copy>
<echomessage="Creatingwarfile${assemble.dir}/${appname}-web.war"level="verbose"/>
<jarjarfile="${assemble.dir}/${appname}-web.war"update="true">
<filesetdir="${build.classes.dir}/tmp"casesensitive="yes">
<includename="**/*class*"/>
<includename="**/${handler.name}"/>
</fileset>
<filesetdir="${build.classes.dir}/tmp/"casesensitive="true">
<includename="WEB-INF/web.xml"/>
</fileset>
<filesetdir="${build.classes.dir}/tmp"casesensitive="yes">
<includename="WEB-INF/wsdl/*.*"/>
</fileset>
</jar>
<echomessage="createdwarfile${assemble.dir}/${appname}-web.war"level="verbose"/>
</target>

我们可以通过执行下面的命令来部署已经生成的war文件:
antdeploy-app
这等同于执行下面的asadmin部署命令(都是在同一行):
bash$GLASSFISH_HOME/bin/asadmindeploy--useradmin
--passwordfilepasswd--hostlocalhost--port4848
--contextrootjaxws-webservice--upload=true--targetserver
编写构建客户端
在你部署完这个web服务之后,你可以通过一个客户端程序来访问它。下面是构建这个客户端的步骤:
1编写客户端
2生成编绎这个客户端必须要有的可移植制品。
3编绎客户端。
4运行客户端。

5.1编写客户端
下面的程序,JAXWSClient,是一个独立的客户端程序,它在这个例子所提供的代码里可以找到。这个客户端类调用了部署好的服务的一个add操作十次,从数字0到9挨个加10.
packageclient;
importjavax.xml.ws.WebServiceRef;
importcom.techtip.jaxws.sample.CalculatorService;
importcom.techtip.jaxws.sample.Calculator;
publicclassJAXWSClient...{
@WebServiceRef(wsdlLocation=
"http://localhost:8080/jaxws-webservice/CalculatorService?WSDL")
staticCalculatorServiceservice;
publicstaticvoidmain(String[]args)...{
try...{
JAXWSClientclient=newJAXWSClient();
client.doTest(args);
}catch(Exceptione)...{
e.printStackTrace();
}
}
publicvoiddoTest(String[]args)...{
try...{
System.out.println(
"Retrievingportfromtheservice"+service);
Calculatorport=service.getCalculatorPort();
System.out.println(
"Invokingaddoperationonthecalculatorport");
for(inti=0;i>10;i++)...{
intret=port.add(i,10);
if(ret!=(i+10))...{
System.out.println("Unexpectedgreeting"+ret);
return;
}
System.out.println(
"Adding:"+i+"+10="+ret);
}
}catch(Exceptione)...{
e.printStackTrace();
}
}
}

研究下上面代码的特点,在JAXWSClient类里的@WebServiceRef注释是用来定义一个web服务的引用。@WebServiceRef注释的wsdlLocation参数它指向了一个所要引用的服务的WSDL文件。@WebServiceRef注释支持其它的可选属性,就像在JSR224里所说的。静态变量名service将会被客户端容器在运行时被动态地注入。
注意到JAXWSClient的import语句:
com.techtip.jaxws.sample.CalculatorServiceandcom.techtip.jaxws.sample.Calculator.
这些import语句是对那些在下一步里将要产生的可移植制品的声明。CalculatorService是服务实现类的可移植制品。Calculator是一个对于服务端点的Java接口,它是从@WebServiceRef注释中的wsdlLocation属性所说明的WSDL文件生成的。

这个客户端从getWebServiceRefNamePort方法得到一个CalculatorService,从而得到一个端点Calculator接口Calculatorport=service.getCalculatorPort();WebServiceRefName是@WebServiceRef注释的name属性,或者说是在生成的WSDL文件里WSDP端口的值。在获得了这个端点后,客户端调用了十次加的操作。

5.2生成客户端的可移植的制品
就像在之前所提到的,CalculatorService跟Calculator都是可移植的制品。为了生成客户端所需的所有制品,定位到jaxws-techtip文件夹,并且在DOS窗口下输入下面的命令:
antgenerate-client-artifacts
这相当于执行下面的wsimport命令(都在同一行里):
$GLASSFISH_HOME/bin/wsimport-keep-d./build/classes/client
http://localhost:8080/jaxws-webservice/CalculatorService?WSDL
这将会在jaxws-techtip文件夹的build/classes/client/com/techtip/jaxws/sample目录下生成以下的制品:
Add.java
Add.class
AddResponse.java
AddResponse.class
Calculator.java
Calculator.class
CalculatorService.java
CalculatorService.class
package-info.java
package-info.class
ObjectFactory.class
ObjectFactory.java
5.3编绎客户端类
下一步需要做的工作就是编绎客户端类。我们可以通过输入下面的命令来完成这项工作:
antcompile-client
ant编绎任务将会编绎client/JAXWSClient并且把class文件写到build/classes/client子目录下。它等同于运行下面的命令(都是在同一行):
javac-d./build/classes/client
-classpath$GLASSFISH_HOME/lib/javaee.jar:
$GLASSFISH_HOME/lib/appserv-ws.jar:
./build/classes/clientclient/JAXWSClient.java
54运行客户端
为了了解这个例子是如何工作的,运行下面的命令:
antruntest-jaxws
它就相当于在build/classes/client文件夹下,运行下面的命令:
$GLASSFISH_HOME/bin/appclient-mainclassclient.JAXWSClient
在DOS窗口可以看到类似下面的输出:
runtest-jaxws:
[echo]Executingappclientwithclientclassas
client.JAXWSClient
[exec]Retrievingportfromtheservice
com.techtip.jaxws.sample.CalculatorService@162522b
[exec]Invokingaddoperationonthecalculatorport
[exec]Adding:0+10=10
[exec]Adding:1+10=11
[exec]Adding:2+10=12
[exec]Adding:3+10=13
[exec]Adding:4+10=14
[exec]Adding:5+10=15
[exec]Adding:6+10=16
[exec]Adding:7+10=17
[exec]Adding:8+10=18
[exec]Adding:9+10=19
all:
BUILDSUCCESSFUL
Totaltime:6seconds
(完)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: