服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

weblogic 9新特性:web services(组图)


  本文讨论weblogic server 9(下简称wls9)中的新特性:java web service (jws)。wls9的web services子系统实现了j2ee 1.4中的web services的新标准: enterprise web services 1.1 specification (jsr-921)。该规范定义了标准的j2ee web service打包格式,部署模块以及运行时服务。
  
  jsr-921是j2ee 1.3中web services规范jsr-109的1.1维护版本。在web services 1.1中描述了j2ee web service的业务逻辑有两种实现方式:一种是使用web容器中的javabean,另一种是使用ejb容器中的无状态session bean。与旧的web services开发方式不同,bea建议使用jws这种基于注释的web services编程方式以简化开发。这种编程方式的开发过程大概是这样,利用jdk5的新特性元数据注释(jsr-175),在编写上述的java bean或ejb的bean类时在业务逻辑代码中添加一些特殊注释,然后用ant的一些扩展任务可以生成一些相关java类代码(主要是ejb的存根、桩)和配置文件,最后自动编译这些类代码并自动打包。所以可以说jws方式是web services新标准的核心。jws文件实际就是普通的.java文件(扩展名依旧是.java),通过添加注释来制定ws的特性。这些注释在jsr181中有完整的说明。如果web service用java bean类实现,自动打包后会包含web.xml,weblogic.xml, webservices.xml,weblogic-webservices.xml,jax-rpc数据类型映射文件和wsdl等,并被打包成标准web应用的war。如果用ejb实现,则会包含ejb-jar.xml和weblogic-ejb.jar.xml等,并被自动打包成标准ejb的jar。下图描述了jws文件生成可部署的j2ee模块的详细过程。后面我们会用两个例子详细说明如何开发、部署基于java bean和基于ejb的web services。
  
 weblogic 9新特性:web services(组图)(图一)

  jsr181与jsr175介绍
  
  我们先来看一段典型的使用jsr175特征的代码。
  
  package webservices.jsr181.pojo;
  
  import javax.jws.webmethod;
  import javax.jws.webservice;
  
  @webservice(name="stringchangerport", targetnamespace="http://wwtt.bea.com")
  
  public class stringchanger {
  @webmethod()
  public string toupper(string upperreqstring)
  {
  ……
  这个类的源代码和普通的java代码没太多区别,但和普通java代码不同的是这里面还包含了很多以@开头的代码,或者称为注释,也就是在java 5中的新语法,jsr-175。jsr-175规范只是定义这种语法规则,而用这种语法来如何将这个类生成一个web service接口,则需要由jsr-181规范来决定。所以这些jsr-175的注释才真正决定了这个web service的行为和外观。
  
  也许你会觉得这种语法比较奇怪,有些像普通java方法的语法,只是前面多了一个@。实际在jsr175规范的早期,该语法并不是像现在这样的。如果按早期写法,@webservice()会该写为:
  
  /**
  * @webservice(......)
  */  后来出于简化,成了现在的样子。如果使用weblogic platform 7.x或8.x产品,会在许多其专有的代码文件中看到这种格式的注释。由于撰写本文时weblogic platform 9还没有发布。发布后是否那些专有代码会使用基于jsr-175的语法还不得而知,但可以确定的是在weblgic server 9中这种语法已经被全面支持了,无论在web service中,还是在ejb中。
  
  事实上jsr 181是bea提出的用于加速web services开发的一种基于注释驱动的编程模式,并被批准纳入到j2ee 1.5标准。jsr181提供了一种简单的web service开发编程模型和标准的编译及部署方式。只需要编写jsr-175风格的注释就可以制定wsdl,消息产生属性,安全认证方式,以及特定的消息头。
  
  练习的预备工作
  
  准备必要软件。
  
  进行练习前需要预先安装wls9正式版,可以到bea官方网站上免费下载。本练习可在能安装wls9的任何操作系统上完成,为了方便起见,文中仅以在windows xp上开发为例。此外本文中代码的开发环境为eclipse 3.1及对应的lomboz,当然如您所愿任何其他支持ant的开发环境都是可以的。
  
  配置weblogic server。
  
  准备好上述软件后,首先用配置创建一个新的wls domain。记得用户名和密码要都设为weblogic,端口为7001。创建好后启动该domain,并用浏览器启动相应的console,用帐户weblogic/weblogic登录进入。
  
  配置eclipse。
  
  如果希望eclipse的配置尽量吻合本文的环境,可参考我的另一篇文章:“使用eclipse加速weblogic server开发”的第一步到第二步。配置好后在eclipse的file->new project中选取java project,在project name中将我们这个练习的名字设为jsr-181 web services或任何你喜欢的名字,jdk compliance中选择“use a project specific compliance 5.0”,其余保持默认。一个符合我们需要的project就建好了。
  
  修改脚本文件。
  
  本练习所有的构建过程都由ant来完成,因此我们需要添加一些ant的脚本配置文件。属性文件,宏定义文件可以完全参照《使用eclipse加速weblogic server开发》,因此只需要吧那里面的那三个文件拿过来用就可以了。
  
  需要修改的是build.xml文件,这里定义的属性主要是为后面两个例子设置一些路径。
  
  <?xml version="1.0"?>
  <project name="wls v9 jsr-181 web services" basedir=".">
  
  <property file="wls-build-tools/weblogicserver.properties" />
  <import file="wls-build-tools/weblogicserver.macrodef" />
  <taskdef file="wls-build-tools/weblogictasks.properties" classpathref="jwsbuild.class.path" />
  
  <property name="apps.src.dir" location="." />
  <property name="apps.dest.dir" location="${temp.dir}" />
  <property name="clients.src.dir" location="." />
  <property name="clients.dest.dir" location="${temp.dir}" />
  <property name="clients.package.name" value="client.test"/>
  <property name="clients.package.path" value="client/test"/>
  
  <property name="jbapp.context.name" value="jb" />
  <property name="jbapp.package.name" value="webservices.jsr181.pojo"/>
  <property name="jbapp.src.dir" location="${apps.src.dir}/webservices/jsr181/pojo"/>
  <property name="jbapp.jwssource.file" value="stringchanger.java" />
  <property name="jbapp.dest.dir" location="${apps.dest.dir}/${jbapp.context.name}" />
  <property name="jbapp.service.name" value="stringchangerservice" />
  <property name="jbapp.wsdl.url" value="http://${domain.address}:${domain.port}/${jbapp.context.name}/${jbapp.service.name}?wsdl" />
  <property name="jbapp.deploy.name" value="wls v9 jsr-181 javabean web service" />
  
  <property name="ejbapp.context.name" value="ejb" />
  <property name="ejbapp.package.name" value="webservices.jsr181.ejb"/>
  <property name="ejbapp.src.dir" location="${apps.src.dir}/webservices/jsr181/ejb"/>
  <property name="ejbapp.jwssource.file" value="purchaseorder.java" />
  <property name="ejbapp.dest.dir" location="${apps.dest.dir}/${ejbapp.context.name}" />
  <property name="ejbapp.service.name" value="purchaseorderservice" />
  <property name="ejbapp.wsdl.url" value="http://${domain.address}:${domain.port}/${ejbapp.context.name}/${ejbapp.service.name}?wsdl" />
  <property name="ejbapp.wsdl.local" value="jar:file:${apps.dest.dir}/${ejbapp.context.name}/purchaseorder.jar!/meta-inf/${ejbapp.service.name}.wsdl" />
  <property name="ejbapp.deploy.name" value="wls v9 jsr-181 ejb web service" />
  
  <path id="jwsbuild.class.path">
  <fileset dir="${weblogic.home}/server/lib">
  <include name="weblogic.jar" />
  <include name="xbean.jar" />
  </fileset>
  <fileset dir="${jdk5.home}/lib">
  <include name="tools.jar" />
  </fileset>
  </path>
  
  <path id="javabuild.class.path">
  <pathelement path="${clients.dest.dir}" />
  <fileset dir="${weblogic.home}/server/lib">
  <include name="webserviceclient.jar" />
  </fileset>
  </path>
  
  <!--后面的练习中我们将根据需要在此添加一些target。-->
  
  </project>
  
  如何快速查看例子的结果,而跳过开发环节。
  
  做好1到4步骤就可以按照后面几节所述完成练习。但如果想快速看一下练习结果,将本文附件solution包括所有源代码。解压到您磁盘任何位置,用eclipse创建好一空的名为jsr-181 web services的project后,用solution解出的jsr-181 web services文件夹替换这个project的文件夹。最后在eclipse的package explorer中刷新一下,就浏览已经开发配置好eclipse project代码了。修改项目的wls-build-tools路径下weblogicserver.properties中的wls和jdk环境变量,然后就可以执行ant脚本中的任务来编译,部署,测试等步骤。
  
  开发基于javabean的web services
  
  基于javabean的web servics是最简单的一种方式。我们只需要在普通的javabean码中添加一些符合jsr181的注释,在build.xml中调用wls提供的扩展ant task,就可以完成一个完整的web services。
  
  创建一个java bean。
  
  在project的根目录下创建一个类名为stringchanger,包名为webservices.jsr181.pojo,写入如下内容:
  
  package webservices.jsr181.pojo;
  
  import javax.jws.webmethod;
  import javax.jws.webservice;
  import javax.jws.soap.soapbinding;
  import weblogic.jws.wlhttptransport;
  
  @webservice(name="stringchangerport", targetnamespace="http://bea.com")
  @soapbinding(style=soapbinding.style.rpc, use=soapbinding.use.encoded)
  @wlhttptransport(contextpath="jb", serviceuri="stringchangerservice")
  
  public class stringchanger {
  @webmethod()
  public string toupper(string upperreqstring)
  {
  string upper = upperreqstring.touppercase();
  system.out.println("toupper request: " + upperreqstring);
  system.out.println("toupper reply: " + upper);
  return(upper);
  }
  
  @webmethod(operationname="tolower")
  public string tolowercase(string lowerreqstring)
  {
  string lower = lowerreqstring.tolowercase();
  system.out.println("tolowercase request: " + lowerreqstring);
  system.out.println("tolowercase reply: " + lower);
  return(lower);
  }
  }
  
  这个类是用于实现我们这个web services模块的业务逻辑,以及描述这个web service接口。该类中包含两个public的业务方法:toupper(string): string和tolowercase(string): string。其中的逻辑也很简单:前者将传入的字符串全变成大写,后者则全变成小写。并且两个方法都将在终端上将操作过程打印出来。除了这两法方法,其余都是用于描述web service接口的jsr-181注释。
  
  先看一些类级别的注释。@webservice()表示这个类可以生成web service。name用于映射到wsdl文件的<wsdl:porttype>元素,可以在生成的wsdl中找到<wsdl:porttype>的值为stringchangerport。targetnamespace用于指定wsdl文件中元素的命名空间,能在生成的wsdl中找到对应的targetnamespace="http://bea.com"。@soapbinding()表示这个服务可以映射到一个soap消息中。style用于指定soap消息请求和回应的编码方式为rpc。use用于指定soap消息请求和回应是明文还是密文,此处表示为密文。@wlhttptransport是一个weblogic专用的注释,用于指生成的配置文件中的上下文路径和这个web service的uri。contextpath用于指定上下文路径为jb,也就是说可以用 http://localhost:7001/jb/ 这个url来调用这个web services应用。serviceuri表示客户端访问这个web service的uri为 http://localhost:7001/jb/stringchangerservice。
  
  再看一些方法级别的注释。方法级注释为@webmethod()。operationname为操作的名字,用于映射到wsdl文件的<wsdl:operation>元素。默认值为对应的方法名。因此在这个javabean生成的web service中toupper方法对应的操作名为toupper,tolowercase方法对应的操作名为tolower。
  
  编写build.xml target。
  
  <target name="build.jb" depends="clean.jb">
  <jwsc srcdir="${jbapp.src.dir}" destdir="${jbapp.dest.dir}" listfiles="true" classpathref="jwsbuild.class.path">
  <jws file="${jbapp.jwssource.file}" />
  </jwsc>
  </target>
  <target name="deploy.jb" depends="check.jb" if="jb.exists">
  <wls.deploy deploy.dir="${jbapp.dest.dir}" deploy.name="${jbapp.deploy.name}" />
  </target>
  
  build.jb 这个target主要用于建立一个可部署的web services模块。jwsc这个任务是用于分析jws文件中的注释,生成对应java文件配置文件,编译代码,最后在destdir指定的位置生成这个web services的war包。
  
  deploy.jb这个target主要用于把web service模块部署到wls domain中。wls.deploy是一个在weblogicserver.macrodef中定义的task,调用wls的ant扩展任务wldeploy。
  
  编译web services。
  
  现在我们在ant view中执行任务build.ws.pojo,可以看到在console窗口显示出对应的操作过程。
  
  buildfile: c:/project/eclipse31/workspace/jsr-181 web services/build.xml
  clean.jb:
  [delete] deleting directory c:/temp/jb
  [mkdir] created dir: c:/temp/jb
  build.jb:
  [jwsc] 1 jws files will be processed.
  [jwsc] processing jws: c:/project/eclipse31/workspace/jsr-181 web services/webservices/jsr181/pojo/stringchanger.java
  [jwsc] jws: c:/project/eclipse31/workspace/jsr-181 web services/webservices/jsr181/pojo/stringchanger.java validated.
  [jwsc] compiling 2 source files to c:/temp/_ukbwfm
  [jwsc] c:/temp/_ukbwfm/stringchangerporttype.java
  [jwsc] c:/project/eclipse31/workspace/jsr-181 web services/webservices/jsr181/pojo/stringchanger.java
  [jwsc] building war: c:/temp/jb/stringchanger.war
  [jwsc] created jws deployment file: c:/temp/jb/stringchanger.war
  [antutil.deletedir] deleting directory c:/temp/_ukbwfm
  build successful
  total time: 22 seconds
  
  打开目录c:/temp/jb,我们能看到生成了两个文件夹和一个war文件。在文件夹meta-inf下的 application.xml中的<web-uri>元素的值来自jws中的注释@wlhttptransport。打开生成的war文件我们能看web-inf路径下已经生成了一些对应的配置文件。查看其中的wsdl文件名为stringchangerservice.wsdl,这也是来自jws中的注释@wlhttptransport。在wsdl文件中能看到targetnamespace为http://wwtt.bea.com,这是来自jws中的注释@webservice。同样我们能在该文件中看到service元素中port为stringchangerport,也是来自@webservice。在这个文件中包括了两个operation元素,name分别为tolower和toupper,对应到jws中两个注释@webmethod。同时我们能看到对应的style为rpc,use为encoded。这些都符合我们在jws的@soapbinding注释中的设置。同时我们能看到该war的web-inf/classes/webservices/jsr181/pojo 目录中包含两个class文件:stringchanger.class内是stringchanger.java描述的业务逻辑,stringchangerporttype是为这个类生成的接口。stringchangerporttype会在后面生成web services代码时被自动调用。
  
  public interface stringchangerporttype extends remote{
  public abstract string tolowercase(string s)
  throws remoteexception;
  public abstract string toupper(string s)
  throws remoteexception;
  }
  
  部署web service
  
  我们在ant view中执行任务deploy.jb,可以看到在console窗口中显示对应部署过程。
  
  buildfile: c:/project/eclipse31/workspace/jsr-181 web services/build.xml
  check.jb:
  deploy.jb:
  [wldeploy] weblogic.deployer -noexit -name wls v9 jsr-181 javabean web service -source c:/temp/jb -targets adminserver -adminurl t3://localhost:7001 -user weblogic -password ******** -deploy
  [wldeploy] weblogic.deployer invoked with options: -noexit -name wls v9 jsr-181 javabean web service -source c:/temp/jb -targets adminserver -adminurl t3://localhost:7001 -user weblogic -deploy
  [wldeploy] <2005-11-28 下午06时12分15秒 cst>
  [wldeploy] task 13 initiated: [deployer:149026]deploy application wls v9 jsr-181 javabean web service on adminserver.
  [wldeploy] task 13 completed: [deployer:149026]deploy application wls v9 jsr-181 javabean web service on adminserver.
  [wldeploy] target state: deploy completed on server adminserver
  build successful
  total time: 14 seconds
  
  用浏览器打开http://localhost:7001/console/,用weblogic/webogic登录,在左边目录树的deploy展开能看到已经部署了一个名为“wls v9 jsr-181 javabean web service”的企业应用(enterprise application),状态为active。
  
 weblogic 9新特性:web services(组图)(图二)

  测试
  
  用浏览器打开 http://localhost:7001/jb/stringchangerservice?wsdl ,可以看到一个展开的wsdl文件。这个文件的内容和我们前面在war中看到的wsdl文件应该是完全一致的。到此我们已经学会了开发一个简单的基于javabean的web service应用。
  
  基于javabean的web service开发测试客户端
  
  从上面的例子我们已经了解了如何开发,部署及测试一个web services模块,下面我们要学习如何开发一个web service客户端来调用web service逻辑。
  
  编写build.xml target
  
  <target name="build.jbclient">
  <clientgen wsdl="${jbapp.wsdl.url}" destdir="${clients.src.dir}" packagename="${clients.package.name}" />
  <javac srcdir="${clients.src.dir}" destdir="${clients.dest.dir}" includes="${clients.package.path}/*.java" debug="on" classpathref="javabuild.class.path" />
  </target>
  <target name="build.jbdriver">
  <javac srcdir="${jbapp.src.dir}" destdir="${clients.dest.dir}" includes="*.java" classpathref="javabuild.class.path" />
  </target>
  
  build.jbclient 这个target主要用于建立一个web services模块的客户端,其中包含两个任务。clientgen这个任务可以根据一个wsdl文件生成一组调用该web service的客户端文件。clientgen的属性wsdl指定wsdl文件的位置,packagename指定生成的测试代码的包名。javac这个任务将生成的客户端java代码文件编译成对应的class文件。
  
  build.jbdriver这个target主要用于编译测试类。
  
  生成并编译客户端代码
  
  现在我们在ant view中执行任务build.jbclient,可以看到在console窗口显示出对应的操作过程。
  
  buildfile: c:/project/eclipse31/workspace/jsr-181 web services/build.xml
  build.jbclient:
  [clientgen] generating client from http://localhost:7001/jb/stringchangerservice?wsdl ...
  [clientgen] getting partner link
  [clientgen] package name is client.test
  [clientgen] destdir is c:/project/eclipse31/workspace/jsr-181 web services
  [clientgen] class name is stringchangerport_stub
  [clientgen] service class name is stringchangerservice
  [clientgen] porttype name is stringchangerport
  [clientgen] service impl name is stringchangerservice_impl
  [javac] compiling 4 source files to c:/temp
  build successful
  total time: 20 seconds
  
  回到eclipse的package explorer视图,在“jsr-181 web services”上右键选refresh,能看到在项目中增加了一个名为client.test的包。展开这个包能看到里面包含若干java文件,xml文件和wsdl文件。这些文件就是自动生成的客户端代码。打开资源管理器到c:/temp/client/test,能看到生成的客户端代码的class文件。
  
 weblogic 9新特性:web services(组图)(图三)

  我们注意到,一共生成了4个类,接口stringchangerport和其实现类stringchangerport_stub是我们在stringchanger类中用@webservice(name="stringchangerport",......)指定的,用于定义业务方法的参数类型和参数转换传输的方法。接口stringchangerservice和其实现类stringchangerservice_impl是我们在stringchanger类中用@wlhttptransport(......, serviceuri="stringchangerservice")中指定的,用于获得service连接,定义消息的收发方式。
  
  创建并编译一个测试类
  
  下面我们创建一个测试类testdriver_pojo来调用刚才我们创建的web service客户端。和刚才创建java bean一样,在webservices.jsr181.pojo中创建一个类testdriver_pojo,写入如下内容:
  
  package webservices.jsr181.pojo;
  
  import java.rmi.remoteexception;
  import javax.xml.rpc.serviceexception;
  import client.test.stringchangerport;
  import client.test.stringchangerservice;
  import client.test.stringchangerservice_impl;
  
  public class testdriver_pojo {
  
  public static void main(string[] args) throws serviceexception, remoteexception{
  string url = "http://localhost:7001/jb/stringchangerservice?wsdl";
  stringchangerservice service = new stringchangerservice_impl(url);
  stringchangerport port = service.getstringchangerportsoapport();
  string teststring = "this is my test string ;-)";
  system.out.println("toupper request: " + teststring);
  system.out.println("toupper results: " + port.toupper(teststring));
  system.out.println("tolower request: " + teststring);
  system.out.println("tolower results: " + port.tolower(teststring));
  }
  }
  
  我们能看到,一个java类调用一个web service客户端是非常简单的。首先通过提供wsdl文件的位置来获得客户端类(stringchangerservice)以及soap接口(stringchangerport)。然后就可以通过服务名来调用这个soap接口提供的各种服务(toupper和tolower)。
  
  运行测试类观察结果
  
  因为测试类只是用于测试,简化起见我们直接运行这个类而不使用ant。右键点这个类的java文件,选择“run as…=> java application”。这时我们在console能看到运行结果。如果一切正确:
  
  toupper request: this is my test string ;-)
  toupper results: this is my test string ;-)
  tolower request: this is my test string ;-)
  tolower results: this is my test string ;-)
  
  到此,我们已经成功创建了一个基于jsr-181的web service以及对应客户端。如果有兴趣,可以试着在jws文件中修改一些代码和注释,看看这些代码和注释会影响什么。无论如何,这会加深你对jsr-181的理解。
  
  开发基于session ejb的web service
  
  使用基于ejb的web servics和基于javabean的方式类似。我们只需在bean类中添加一些符合jsr181的注释,在build.xml中调用wls提供的扩展ant task来完成web services。
  
  1. 创建一个ejb。
  
  在project的根目录下创建一个类名为purchaseorder,包名为webservices.jsr181.ejb,写入如下内容:
  
  package webservices.jsr181.ejb;
  
  import java.rmi.remoteexception;
  
  import javax.ejb.ejbexception;
  import javax.ejb.sessionbean;
  import javax.ejb.sessioncontext;
  import javax.jws.webmethod;
  import javax.jws.webservice;
  import javax.jws.soap.soapbinding;
  
  import weblogic.ejbgen.constants;
  import weblogic.ejbgen.filegeneration;
  import weblogic.ejbgen.jndiname;
  import weblogic.ejbgen.remotemethod;
  import weblogic.ejbgen.session;
  import weblogic.jws.wlhttptransport;
  
  @session(ejbname = "purchaseorderejb", serviceendpoint = "webservices.jsr181.ejb.purchaseorderporttype")
  @jndiname(remote = "purchaseorderejb.remote")
  @filegeneration(remoteclass = constants.bool.true, remoteclassname = "purchaseorderremote", remotehome = constants.bool.true, remotehomename = "purchaseorderhome")
  @webservice(name="purchaseorderport", servicename="purchaseorderservice", targetnamespace="http://bea.com /purchaseorder")
  @soapbinding(style=soapbinding.style.document, use=soapbinding.use.literal, parameterstyle=soapbinding.parameterstyle.bare)
  @wlhttptransport(portname="purchaseorderport", contextpath="ejb", serviceuri="purchaseorderservice")
  
  public class purchaseorder implements sessionbean {
  
  private static final long serialversionuid = 1l;
  
  public void ejbcreate() {}
  
  @remotemethod()
  @webmethod()
  public string toupper(string upperreqstring)
  {
  string upper = upperreqstring.touppercase();
  system.out.println("toupper request: " + upperreqstring);
  system.out.println("toupper reply: " + upper);
  return(upper);
  }
  
  public void setsessioncontext(sessioncontext arg0) throws ejbexception,
  remoteexception {}
  
  public void ejbremove() throws ejbexception, remoteexception {}
  
  public void ejbactivate() throws ejbexception, remoteexception {}
  
  public void ejbpassivate() throws ejbexception, remoteexception {}
  
  }
  
  这个类是我们创建的ejb的bean类,并通过jsr175方式描述该ejb接口以及生成的web service接口。该类中只包含一个public的业务方法:toupper(string): string,其余都是ejb要求的方法,以及用于描述ejb和web service的jsr-175注释。
  
  先看一些类级别的注释。和基于javabean的jws类似,包含了jsr181定义的三行注释@webservice(),@soapbinding()和@wlhttptransport()。与javabean不同的是这里还包括一些用于生成ejb配置文件和接口的注释。@session表示这是一个session bean,属性ejbname和serviceendpoint分别表示ejb的名字和接口名。@jndiname()中属性remote表示这个ejb发布在jndi上的地址为purchaseorderejb.remote。@filegeneration()表示由这个bean类生成的代码文件。属性remoteclass,remoteclassname,remotehome和remotehomename分别指定使用远程接口和远程home接口,并且这两个接口为purchaseorderremote和purchaseorderhome。
  
  在方法级别上,除了和javabean类似用@webmethod()声明暴露的web service操作外,用@remotemethod()将这个方法指定为发布到远程接口上的方法。
  
  2. 编写build.xml target。
  
  <target name=”build.ejb” depends=”clean.ejb”>
  <jwsc srcdir=”${ejbapp.src.dir}” destdir=”${ejbapp.dest.dir}” listfiles=”true” classpathref=”jwsbuild.class.path”>
  <jws file=”${ejbapp.jwssource.file}” />
  </jwsc>
  </target>
  <target name=”deploy.ejb” depends=”check.ejb” if=”ejb.exists”>
  <wls.deploy deploy.dir=”${ejbapp.dest.dir}” deploy.name=”${ejbapp.deploy.name}” />
  </target>
  
  build.jb和deploy.jb两个target主要用于建立一个可部署的web services模块并部署到domain中。这与前面javabean例子使用方式完全一致。
  
  3. 编译web services。
  
  现在我们在ant view中执行任务build.ejb,可以看到在console窗口显示出对应的操作过程。
  
  buildfile: c:/project/eclipse31/workspace/jsr-181 web services/build.xml
  clean.ejb:
  [delete] deleting directory c:/temp/ejb
  [mkdir] created dir: c:/temp/ejb
  build.ejb:
  [jwsc] 1 jws files will be processed.
  [jwsc] processing jws: c:/project/eclipse31/workspace/jsr-181 web services/webservices/jsr181/ejb/purchaseorder.java
  [jwsc] jws: c:/project/eclipse31/workspace/jsr-181 web services/webservices/jsr181/ejb/purchaseorder.java validated.
  [jwsc] ejbgen 9.0
  [jwsc] creating c:/temp/_f26ur6/purchaseorderhome.java
  [jwsc] creating c:/temp/_f26ur6/purchaseorderremote.java
  [jwsc] creating c:/temp/_f26ur6//ejb-jar.xml
  [jwsc] creating c:/temp/_f26ur6//weblogic-ejb-jar.xml
  [jwsc] compiling 4 source files to c:/temp/_f26ur6
  [jwsc] c:/temp/_f26ur6/purchaseorderhome.java
  [jwsc] c:/temp/_f26ur6/purchaseorderporttype.java
  [jwsc] c:/temp/_f26ur6/purchaseorderremote.java
  [jwsc] c:/project/eclipse31/workspace/jsr-181 web services/webservices/jsr181/ejb/purchaseorder.java
  [jwsc] building jar: c:/temp/ejb/purchaseorder.jar
  [jwsc] created jws deployment file: c:/temp/ejb/purchaseorder.jar
  [antutil.deletedir] deleting directory c:/temp/_f26ur6
  creating c:/temp/_f26ur6/ejbgen-build.xml
  build successful
  total time: 17 seconds
  
  打开目录c:/temp/ejb,我们能看到生成了两个文件夹和一个jar文件。在文件夹meta-inf下的。打开生成的jar文件我们能看meta-inf路径下已经生成了一些对应的配置文件。其中大部分和在javabean中生成的配置文件类似,此外还包括一些与ejb相关的配置文件,比如weblogic-ejb-jar.xml,ejbgen-build.xml和ejb-jar.xml,没有了与web应用相关的配置文件weblogic.xml和web.xml
  
  部署web service
  
  我们在ant view中执行任务deploy.ejb,可以看到在console窗口中显示对应部署过程。
  
  buildfile: c:/project/eclipse31/workspace/jsr-181 web services/build.xml
  check.ejb:
  deploy.ejb:
  [wldeploy] weblogic.deployer 每noexit 每name wls v9 jsr-181 ejb web service 每source c:/temp/ejb 每targets adminserver 每adminurl t3://localhost:7001 每user weblogic 每password ******** -deploy
  [wldeploy] weblogic.deployer invoked with options: -noexit 每name wls v9 jsr-181 ejb web service 每source c:/temp/ejb 每targets adminserver 每adminurl t3://localhost:7001 每user weblogic 每deploy
  [wldeploy] <2005-11-28 ?b??09?c21煦47镞 cst>
  [wldeploy] task 1 initiated: [deployer:149026]deploy application wls v9 jsr-181 ejb web service on adminserver.
  [wldeploy] task 1 completed: [deployer:149026]deploy application wls v9 jsr-181 ejb web service on adminserver.
  [wldeploy] target state: deploy completed on server adminserver
  build successful
  total time: 7 seconds
  
  用浏览器打开http://localhost:7001/console/,用weblogic/webogic登录,在左边目录树的deploy展开能看到已经部署了一个名为“wls v9 jsr-181 ejb web service”的企业应用(enterprise application),状态为active。
  
 weblogic 9新特性:web services(组图)(图四)

  5. 测试
  
  用浏览器打开http://localhost:7001/ejb/stringchangerservice?wsdl,可以看到一个展开的wsdl文件。这个文件的内容和我们前面在jar中看到的wsdl文件应该是完全一致的。
  
  为基于session ejb的web service开发测试客户端
  
  和javabean一样,我们可以为这个基于session bean的web service创建一个客户端,并用来测试。
  
  1. 编写build.xml target
  
  <target name="build.ejbclient">
  <clientgen wsdl="${ejbapp.wsdl.local}" destdir="${clients.src.dir}" packagename="${clients.package.name}"/>
  <javac srcdir="${clients.src.dir}" destdir="${clients.dest.dir}" includes="${clients.package.path}/*.java" debug="on" classpathref="javabuild.class.path" />
  </target>
  <target name="build.ejbdriver">
  <javac srcdir="${ejbapp.src.dir}" destdir="${clients.dest.dir}" includes="*.java" classpathref="javabuild.class.path" />
  </target>
  
  build.jbclient 与build.ejbdriver和javabean中的对应目标也类似。唯一区别的是在clientgen任务中使用的wsdl文件不是来自url,而是来自build.ejb生成的jar包。使用local或url方式对其他客户端代码没有影响,基本这两种方式可以互换使用。
  
  2. 生成并编译客户端代码
  
  现在我们在ant view中执行任务build.jbclient,可以看到在console窗口显示出对应的操作过程。
  
  buildfile: c:/project/eclipse31/workspace/jsr-181 web services/build.xml
  build.ejbclient:
  [clientgen] generating client from jar:file:c:/temp/ejb/purchaseorder.jar!/meta-inf/purchaseorderservice.wsdl …
  [clientgen] getting partner link
  [clientgen] package name is client.test
  [clientgen] destdir is c:/project/eclipse31/workspace/jsr-181 web services
  [clientgen] class name is purchaseorderport_stub
  [clientgen] service class name is purchaseorderservice
  [clientgen] porttype name is purchaseorderport
  [clientgen] service impl name is purchaseorderservice_impl
  [javac] compiling 4 source files to c:/temp
  build successful
  total time: 11 seconds
  
  回到package explorer视图的包client.test。能看到里面又增加了若干java文件,xml文件和wsdl文件。这些文件就是自动生成的客户端代码。打开资源管理器到c:/temp/client/test,能看到生成的客户端代码的class文件。
  
 weblogic 9新特性:web services(组图)(图五)

  我们注意到,一共生成了4个类,stringchangerport和stringchangerport_stub是我们在stringchanger类中用@webservice(name="stringchangerport",......)指定的。stringchangerservice和stringchangerservice_impl是我们在stringchanger类中用@wlhttptransport(......, serviceuri=”stringchangerservice”)中指定的。
  
  3. 创建并编译一个测试类
  
  下面我们在webservices.jsr181.ejb中创建一个类testdriver_ejb,写入如下内容:
  
  package webservices.jsr181.ejb;
  
  import java.rmi.remoteexception;
  
  import javax.xml.rpc.serviceexception;
  
  import client.test.purchaseorderport;
  import client.test.purchaseorderservice;
  import client.test.purchaseorderservice_impl;
  public class testdriver_ejb
  {
  public static void main(string[] args)
  throws serviceexception, remoteexception{
  string         url   = “http://localhost:7001/ejb/purchaseorderservice?wsdl”;
  purchaseorderservice  service = new purchaseorderservice_impl(url);
  purchaseorderport    port  = service.getpurchaseorderport();
  string teststring = “this is my test string ;-)”;
  
  system.out.println(port.toupper(teststring));
  }
  }
  
  这里面的内容和在javabean中也没什么区别。因此我们可以看出来,在web service后端使用什么方式实现,在前端看是完全透明的。
  
  4. 运行测试类观察结果
  
  右键点文件testdriver_ejb.java,选择“run as…=> java application”。这时我们在console能看到运行结果。如果一切正确:
  
  this is my test string ;-)
  到此,我们完成了这个基于ejb的web services的例子。事实上我们可以用各种方法创建web services的业务逻辑,从而轻松的实现系统组件间的松耦合。