微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

快速实践JAX-WS 2.0

 

      本文根据SUN官方网站Enterprise Java Technologies Tech Tips栏目上的一篇文章改写的,所有过程均调试通过。

一.前言

   SOA@H_502_45@思想的核心在于"S"@H_502_45@,凡是从服务的角度去看待系统功能,并且构建和实现应用,都可以认为是SOA@H_502_45@的某种实现形式。下面一段要说的是:SOA@H_502_45@技术的核心在于"O"@H_502_45@--只有做到Service-Orientation@H_502_45@的技术,才能真正称为SOA@H_502_45@技术。

    @H_502_45@怎样才能算作Service-Orientation@H_502_45@?我们再以OO@H_502_45@进行类比:VB@H_502_45@之所以被称为基于对象(Object-Based)@H_502_45@而不是面向对象(Object-Oriented)@H_502_45@的语言,是因为VB@H_502_45@的运行时结构不具有VMT@H_502_45@等基本构造,语法上也不支持私有成员,继承等基础特性,两者结合,就造成无法支持封装,继承,多态等面向对象的关键技术。一句话,VB@H_502_45@不是围绕@H_502_45@对象@H_502_45@这个核心概念设计的语言。对于SOA技术,它也可以从这个角度划分两个层次:一个SOA运行时相关结构标准,例如SOAPWSDL,WS-*等,相当于OO中的对象内部结构,VMT构造等。另外一个则是语言和工具层面的支持,例如基于元数据的服务描述,支持Web Service的类库,Proxy生成工具等,相当于OO语言中提供的基本OO语法,类库,编绎器等。这两个层次共同构成SOA体系结构中的要素,让人们能够围绕服务这个核心概念进行系统开发和应用。因此,一种技术架构,平台或产品要称作SOA,应当同时具备这一两方面的特征。

@H_502_45@所以,下面将要讨论的JAX-WS@H_502_45@技术,从上面的观点来看,也就是SOA@H_502_45@技术的第二个层次,即语言和工具层面的支持--Java@H_502_45@,例如基于元数据的服务描述,支持Web Service@H_502_45@的类库,Proxy@H_502_45@生成工具等.

Java API for XML Web ServicesJAX-WS2.0,Java EE 5平台的一个重要的部分。作为Java API for XML-baseed RPC 1.1JAX-RPC)的后续版本,在JAX-RPC 1.1,开发人员需要写一个接口类Service Endpoint Interface(SEI),JAX-WS 2.0,开发人员一上来就可以直接写自己的实现类. 通过使用annotations,自动生成SEI和其他一些文件.这样有助于开发人员专注于自己想开发的部分,而不必要地分散精力去维护其他的一些附属文件.

.快速实践JAX-WS2.0

下面通过一个两个数相加的简单例子来看看,JAX-WS 2.0 API的应用过程.程序是一个独立的客户端传给服务端两个整数,经过服务端处理后,将结果返回到客户端并打印出来.

.   环境配置.

1. JDK 5.0 or higher

下载: http://java.sun.com/javase/downloads/index.jsp

2. Java EE 5.0 App Server.

这个例子是基于Java EE 5一个开源实现项目GlassFishhttps://glassfish.dev.java.net/public/downloadsindex.html

本例子所需的基本代码的压缩包可以通过这个链接下载。里面包括了这个例子需要的代码,构建脚本和一个build文件

   环境变量的配置:

·                    GLASSFISH_HOME.这个应该指向你安装GlassFish的目录(比如,我系统上的是:J:/Sun/AppServer)

·                    ANT_HOME.这个应该指向ant所安装的目录。在你下载GlassFish bundleAnt已经被包含在里面了。(对于Windows系统,它是在lib/ant子目录)。不过你也可以从Apache Ant Project page.下载Ant。对于这个例子需要Apache ant 1.6.5

·                  JAVA_HOME.这个应该指向你系统上安装的JDK 5.0or higher)的目录。

 同时,把antbin目录添加Path环境变量中去(J:/apache-ant- 1.6.5 /bin),当然了JDKbin目录也加进去了。

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

 

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

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

.编写构建服务端

随着第一步环境配置的完全,现在该开始构建一个web服务了。在这个例子里,web服务是从一个Java类来开发的。为了构建这个web服务:

1 一个端点实现类(endpoint implementation class)

2 编绎这个端点实现类。

3 有选择的产生对web服务的运行必须具备的那些可移植的制品。

4 web服务打包成一个WAR文件并且在App Server中部署它。

1 编写实现类.

进到endpoint/目录下,可以看到里面有一个文件Calculator.java.它是一个端点实现类,具备有对两个整数进行相加的简单服务。

 

JAX-WS 2.0大量地依赖注释(annotations)的使用,它是A Metadata Facility for the Java Programming Language (JSR 175)描述的规范和Web Services Metadata for the Java Platform (JSR 181)描述的规范。

package  endpoint;


import  javax.jws.WebService;

import  javax.jws.WebMethod;


@WebService(

    name
= " Calculator " ,

    serviceName
= " CalculatorService " ,

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

)

public   class  Calculator  {

    
public Calculator() {}


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

    
public int add(int i, int j) {

                
int k = i +j ;

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

 

        
return k;

    }

}

 

    研究上面的实现类Calculator,注意到类里的两个注释的使用@WebService@WebMethod一个正确的端点实现类必须包含有一个@WebService注释。这个注释标注这个类将作为一个web服务对外开放。@WebServicename属性表明了web服务描述语言(WSDL)里的端口类型(portType)在这个例子里是”Calculator”)。而serviceName="CalculatorService"对应的是一个WSDL里的服务元素(service)targetNamespace属性WSDL说明了XML的命名空间。所有的这些属性都是可选的。对于这些属性认值是什么,请参考Web Services Metadata for the Java Platform规范,JSR 181

再来看看另外一个重要的注释@WebMethod,被它注释过的方法说明将它以一个
@WebMethod注释里的operationNameweb服务的方法暴露出来,被其他应用来调用
声明了WSDL里的一个元素WSDL operation在这个例子里,”add”,另外一
属性action =(""),它为WSDL还有一些从这个web服务操作(web service operation)urn:Add
成的元素声明了一个命名空间。这两个属性都是可选的。如果你没有列出来的
话,WSDL操作(operation)的值将会认为方法名,还有action值也会认为
服务的targetNamespace
  2 编绎实现类

  写完了上面的实现类之后,你需要编绎它。点击 开始->程序->Sun Microsystems>“Start Default Server”启动应用服务器或者通过在DOS窗口下敲下面的命令来启动它:<GF_install_dir>/bin/asadmin start-domain domain1,其中GF_install_dir是你安装GlassFish的目录,也就是说先到<GF_install_dir>/bin目录下,然后用命令asadmin start-domain domain1来启动应用服务器。现在将目录转到jaxws-techtip文件夹下,运行下面的ant命令,也就是执行第一个任务complie:

ant compile

@H_901_1502@执行这个命令就相当于执行以下的javac@H_901_1502@命令(@H_901_1502@都是在同一行)@H_901_1502@:

javac -classpath $GLASSFISH_HOME/lib/javaee.jar -d

 ./build/classes/service/   endpoint/Calculator.java

 

3 web服务的执行产生可移植的制品

这一步是可选的。如果在这web服务的部署期间,他们没有和一个可配置的服务单元绑定,GlassFish的部署工具能够自动地产生这些制品。然而对于刚刚接触JAX-WS来说,对于弄清楚整个编程模式来说,通过手动产生地会话会更有帮助,即运行下面的命令:

ant generate-runtime-artifacts

这个任务将会在jaxws-techtip目录下生成build/generated目录,并且运行了下面的wsgen命令(都是在同一行):

$GLASSFISH_HOME/bin/wsgen -cp ./build/classes/service -keep -d ./build/classes/service –r ./build/generated -wsdl endpoint.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的形式或者无状态的session bean形式打包成Web Archive (WAR)文件在这个例子里把它绑定为一个servlet

为了把这个服务打包成一个WAR文件,定位到jaxws-techtip文件夹,并且在DOS窗口上运行下面的命令:

ant pkg-war

对于这个war文件的结构,我们可以到build.xml文件里看看pkg-war目标:

<target name="pkg-war" depends="init-common">
      
<mkdir dir="${assemble.dir}"/>
      
<echo message="my build classes dir is:${build.classes.dir}" level="verbose"/>
      
<mkdir dir="${build.classes.dir}/tmp"/>
      
<mkdir dir="${build.classes.dir}/tmp/WEB-INF"/>
      
<mkdir dir="${build.classes.dir}/tmp/WEB-INF/classes"/>
@H_404_1963@      
<mkdir dir="${build.classes.dir}/tmp/WEB-INF/wsdl"/>
      
<copfile="${web.xml}"
        tofile
="${build.classes.dir}/tmp/WEB-INF/web.xml" failonerror="false"/>
      
<coptodir="${build.classes.dir}/tmp/WEB-INF/classes">
        
<fileset dir="${build.classes.dir}/service">
          
<include name="**/*.class"/>
          
<include name="**/${handler.name}"/>
        
</fileset>
      
</copy>
      
<coptodir="${build.classes.dir}/tmp/WEB-INF/wsdl">
        
<fileset dir="${build.generated.dir}">
          
<include name="**/*.*"/>
        
</fileset>
      
</copy>
      
<echo message="Creating war file ${assemble.dir}/${appname}-web.war" level="verbose"/>
      
<jar jarfile="${assemble.dir}/${appname}-web.war" update="true">
        
<fileset dir="${build.classes.dir}/tmp" casesensitive="yes">
          
<include name="**/*class*"/>
          
<include name="**/${handler.name}"/>
        
</fileset>
        
<fileset dir="${build.classes.dir}/tmp/" casesensitive="true">
          
<include name="WEB-INF/web.xml"/>
        
</fileset>
        
<fileset dir="${build.classes.dir}/tmp" casesensitive="yes">
          
<include name="WEB-INF/wsdl/*.*"/>
        
</fileset>
      
</jar>
      
<echo message="created war file ${assemble.dir}/${appname}-web.war" level="verbose"/>
    
</target>

   我们可以通过执行下面的命令来部署已经生成war文件

   ant deploy-app

 @H_502_2441@这等同于执行下面的asadmin部署命令(都是在同一行)

 bash$GLASSFISH_HOME/bin/asadmin deploy --user admin

   --passwordfile passwd --host localhost --port 4848

   --contextroot jaxws-webservice --upload=true --target server

编写构建客户端

 在你部署完这个web服务之后,你可以通过一个客户端程序来访问它。下面是构建这个客户端的步骤:

1 编写客户端

2 生成编绎这个客户端必须要有的可移植制品。

3 编绎客户端。

4 运行客户端。

 

5.1编写客户端

下面的程序,JAXWSClient,一个独立的客户端程序,它在这个例子所提供的代码里可以找到。这个客户端类调用了部署好的服务的一个add操作十次,从数字09挨个加10.

package client;
   
import
 javax.xml.ws.WebServiceRef;
   
import
 com.techtip.jaxws.sample.CalculatorService;
   
import
 com.techtip.jaxws.sample.Calculator;
 
public class JAXWSClient ...
{
      @WebServiceRef(wsdlLocation=
     "http://localhost:8080/jaxws-webservice/CalculatorService?WSDL")
       
static
 CalculatorService service;
       
public static void main(String[] args) ...
{
         
try ...
{
           JAXWSClient client = 
new
 JAXWSClient();
           client.doTest(args);
         } 
catch(Exception e) ...
{
@H_404_2778@           e.printstacktrace();
         }
      }
      
public void doTest(String[] args) ...
{
        
try ...
{
          System.out.println(
             " Retrieving port from the service " + service);
          Calculator port = service.getCalculatorPort();
          System.out.println(
             " Invoking add operation on the calculator port");
          
for (int i=0;i>10;i++) ...
{
            
int
 ret = port.add(i, 10);
            
if(ret != (i + 10)) ...
{
              System.out.println("Unexpected greeting " + ret);
              
return
;
            }
            System.out.println(
               " Adding : " + i + " + 10 = " + ret);
            }
        } 
catch(Exception e) ...
{
          e.printstacktrace();
        }
      }
   }

研究下上面代码的特点,在JAXWSClient类里的@WebServiceRef注释是用来定义一个web服务的引用。@WebServiceRef注释的wsdlLocation参数它指向了一个所要引用的服务的WSDL文件@WebServiceRef注释支持其它的可选属性,就像在JSR 224里所说的。静态变量名service将会被客户端容器在运行时被动态地注入。

注意到JAXWSClientimport语句:

com.techtip.jaxws.sample.CalculatorService and com.techtip.jaxws.sample.Calculator.

这些import语句是对那些在下一步里将要产生的可移植制品的声明。CalculatorService是服务实现类的可移植制品。Calculator一个对于服务端点的Java接口,它是从@WebServiceRef注释中的wsdlLocation属性所说明的WSDL文件生成的。

 

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

 

5.2生成客户端的可移植的制品

@H_901_1502@就像在之前所提到的,CalculatorService@H_901_1502@跟Calculator@H_901_1502@都是可移植的制品。为了生成客户端所需的所有制品,定位到jaxws-techtip@H_901_1502@文件夹,并且在DOS@H_901_1502@窗口下输入下面的命令:

 ant generate-client-artifacts

@H_901_1502@这相当于执行下面的wsimport@H_901_1502@命令(@H_901_1502@都在同一行里)@H_901_1502@:

$GLASSFISH_HOME/bin/wsimport -keep -d ./build/classes/client

   http://localhost:8080/jaxws-webservice/CalculatorService?WSDL

@H_901_1502@这将会在jaxws-techtip @H_901_1502@文件夹的build/classes/client/com/techtip/jaxws/sample@H_901_1502@目录下生成以下的制品:

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编绎客户端类

 下一步需要做的工作就是编绎客户端类。我们可以通过输入下面的命令来完成这项工作:

ant compile-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/client client/JAXWSClient.java

54运行客户端

为了了解这个例子是如何工作的,运行下面的命令:

ant runtest-jaxws

它就相当于在build/classes/client文件夹下,运行下面的命令:

$GLASSFISH_HOME/bin/appclient -mainclass client.JAXWSClient

@H_901_1502@在DOS@H_901_1502@窗口可以看到类似下面的输出

runtest-jaxws:

        [echo] Executing appclient with client class as

        client.JAXWSClient

        [exec] Retrieving port from the service

        com.techtip.jaxws.sample.CalculatorService@162522b

        [exec] Invoking add operation on the calculator port

        [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:

   BUILD SUCCESSFUL

   Total time: 6 seconds

(完)

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐