﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-ASONG-文章分类-webservice</title><link>http://www.blogjava.net/ASONG/category/12438.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 15:07:54 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 15:07:54 GMT</pubDate><ttl>60</ttl><item><title>用JAX-RPC开发Web服务: Servlet作为Web服务端点</title><link>http://www.blogjava.net/ASONG/articles/54637.html</link><dc:creator>汪松明</dc:creator><author>汪松明</author><pubDate>Fri, 23 Jun 2006 03:01:00 GMT</pubDate><guid>http://www.blogjava.net/ASONG/articles/54637.html</guid><wfw:comment>http://www.blogjava.net/ASONG/comments/54637.html</wfw:comment><comments>http://www.blogjava.net/ASONG/articles/54637.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ASONG/comments/commentRss/54637.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ASONG/services/trackbacks/54637.html</trackback:ping><description><![CDATA[
		<strong>关键词</strong>： <a href="http://tag.bokee.com/tag/JAX-RPC" target="_blank">JAX-RPC</a>    <a href="http://tag.bokee.com/tag/web%B7%FE%CE%F1" target="_blank">web服务</a>                                           
<p></p><p>阅读本文前您需要以下的知识和工具：</p><ul xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><li>JavaTM Web Services Developer Pack 1.1，并且会使用初步使用； 
</li><li>辽倩崾褂靡恢諩JB容器来开发、部署EJB，并且了解怎么在客户端访问EJB组件； 
</li><li>对Apache axis Web服务开发工具有基本的了解； 
</li><li>基本的Java编程知识。 </li></ul><p>如果使用JAX-RPC开发Web服务，我们几种选择：</p><ul xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><li>Servlet作为Web服务端点； 
</li><li>无状态会话Bean作为Web服务端点； 
</li><li>基于消息（如JMS）的应用程序作为Web服务端点。 </li></ul><p>本文以Servlet作为Web服务端点的情况来介绍JAX-RPC Web服务开发，关于本篇文章中案例的介绍详见本系列文章第一篇： <a href="http://www-128.ibm.com/developerworks/cn/webservices/ws-jaxm/part1/index.html" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">《用JAXM开发Web服务》</a>。 </p><p>本文的参考资料见 <a href="http://www-128.ibm.com/developerworks/cn/webservices/ws-jax-rpc/part1/index.html#resources" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">参考资料</a></p><p>本文的全部代码在这里 <a href="http://www-128.ibm.com/developerworks/cn/webservices/ws-jax-rpc/part1/index.html#resources" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">下载</a></p><p><a name="0"><span class="atitle2">JAX-RPC快速入门</span></a><br /></p><p>JAX-RPC，Java™ API for XMLbased RPC，顾名思义，它是一种远程方法调用（或者说远程过程调用），那么它和其它的远程方法调用（RPC， COM，CORBA，RMI）有什么区别呢？我们看一般的远程方法调用的结构，如图1所示。</p><p><a name="N10088"><b></b></a><br /><img height="325" alt="图1 远程方法调用" src="http://www-128.ibm.com/developerworks/cn/webservices/ws-jax-rpc/part1/1.gif" width="533" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" /></p><p>综合比较常用的远程方法调用技术，它们有以下的共性：</p><ul xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><li>在客户端和服务端有通用编程接口； 
</li><li>在客户端有Stub，在服务端有Tie（有的叫Skeleton）； 
</li><li>客户端和服务端有专门的协议进行数据传输。 </li></ul><p>对于通用接口的描述，比如CORBA有IDL of CORBA，Java RMI有Java RMI interface in RMI，对于XMLbased RPC来说，IDL就是WSDL（Web服务描述语言）。那么XMLbased RPC来说，什么是这个结构中的"传输协议"，当然是SOAP，SOAP消息通过以传输文本为基础的协议（HTTP、SMTP、FTP）为载体来使用的，也就是说，SOAP消息的传输建立在HTTP、SMTP、FTP传输协议之上。</p><p>JAX-RPC的构架如下。</p><p><a name="N100AD"><b></b></a><br /><img height="321" alt="图2 JAX-RPC 的构架" src="http://www-128.ibm.com/developerworks/cn/webservices/ws-jax-rpc/part1/2.gif" width="534" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" /></p><p>从上图可以看出，客户端调用的是JAX-RPC服务端点(Service Endpoint)，这个服务端点是通过WSDL语言描述的。在这个体系结构中，对于客户端，可以是JS2E、J2ME或者J2EE平台运行环境；对于服务端，可以是J2EE1.3或者J2EE1.4容器（Servlet容器或者EJB容器）。Apache axis是一个很好的JAX-RPC运行环境实现，同时也提供了优秀的开发工具，本文将使用它进行开发。</p><p>使用Servlet作为服务端点，本案例的基本构架如下图所示。</p><p><a name="N100C3"><b></b></a><br /><img height="310" alt="图3 案例的基本构架" src="http://www-128.ibm.com/developerworks/cn/webservices/ws-jax-rpc/part1/3.gif" width="504" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" /></p><p>客户端通过SOAP消息和JAX-RPC服务端交互，JAX-RPC服务端运行在Servlet容器中，它通过调用EJB容器中的EJB组件来处理具体的业务逻辑。</p><p>使用JAX-RPC开发Web服务，可以按照以下的步骤进行：</p><ol xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><li>服务端点定义； 
</li><li>服务描述； 
</li><li>服务端点实现； 
</li><li>服务端点部署； 
</li><li>服务发布和发现。 </li></ol><p>注意：对于服务的发布和发现，由于机制比较复杂，本文不讨论，可能会在本系列文章进行专题讨论。</p><p><a name="1"><span class="atitle2">开发快速入门</span></a><br /></p><p>一个完整的JAX-RPC开发实例，将按照上面的5个步骤进行，但是我们也可以使用非常简单的方式来发布一个Web服务。在介绍我们的案例前，让我们用一分钟快速开发一个Web服务。</p><p>首先安装好JWSDP，你可以从 <a href="http://java.sun.com/webservices" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://java.sun.com/webservices</a>下载。 </p><p>把本案例源代码中的\src\bookservice.ear\web.war目录拷贝到%JWSDP_HOME%\webapps目录下，web.war文件里已经包括了Apache axis运行环境。</p><p>在%JWSDP_HOME%\classes目录下新建一个HelloWorld.java文件，它的代码如下：</p><p>例程1 最简单的Web服务HelloWorld</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

package com.hellking.webservice;
public class HelloWorld
{
 public String sayHello(String name)
 {
  return "Hello! "+name;
 }
}
</code></pre></td></tr></tbody></table><p>编译这个类，然后编辑%JWSDP_HOME%\webapps\WEB-INF\server-config.wsdd文件，找到记，在其后面加入以下内容：</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code><service provider="java:RPC" name="HelloWorld" /><parameter name="allowedMethods" value="sayHello" /><parameter name="className" value="com.hellking.webservice.HelloWorld" /></code></pre></td></tr></tbody></table><p>在浏览器例输入：</p><a href="http://localhost:8080/web/services/HelloWorld?wsdl" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://localhost:8080/web/services/HelloWorld?wsdl</a><p>如果出现部署WSDL描述文件，那么最简单的Web服务已经部署成功！</p><p>下面我们使用最简单的方式来调用这个Web服务，在浏览器里输入：</p><a href="http://localhost:8080/web/services/HelloWorld?wsdl&amp;method=sayHello&amp;name=hellking" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://localhost:8080/web/services/HelloWorld?wsdl&amp;method=sayHello&amp;name=hellking</a><p>那么在浏览器将会显示以下内容：</p><p>例程2 在浏览器里调用Web服务</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code><!--l version="1.0" encoding="UTF-8"--><envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" /><sayhelloresponse soapenv:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/" /><sayhelloreturn xsi:type="xsd:string" />Hello! hellking</code></pre></td></tr></tbody></table><p>如果结果是这样，那么最简单的Web服务已经部署成功，并且测试也通过了。注意"Hello！hellking"是调用Web服务返回的结果，它是我们期望的。下面我们来看一个完整的Web服务开发的例子。</p><p><a name="2"><span class="atitle2">服务端点定义</span></a><br /></p><p>服务端点定义的工作主要是确定"服务定义接口"（Service Definition Interface），有时也叫Web服务端点接口（Web services endpoint interface）。服务端点定义有两中方法获得：</p><ul xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><li>使用某些工具从WSDL文件获得； 
</li><li>直接使用Java语言编写。 </li></ul><p>Apache axis提供了从WSDL文件中获得Web服务端点的工具。您可以这样使用：</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

java org.apache.axis.wsdl.WSDL2Java (WSDL-file-URL)
</code></pre></td></tr></tbody></table><p>使用这个命令前先设置好以下的环境变量，后面的介绍中还会使用axis工具，它们也要这样设置环境变量：</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

SET AXIS_HOME=<axis安装目录 />
set CLASSPATH=%CLASSPATH%;
%AXIS_HOME%/axis-1_1/lib/axis.jar; 
%AXIS_HOME%/axis-1_1/lib/jaxrpc.jar; 
%AXIS_HOME%/axis-1_1/lib/saaj.jar;
%AXIS_HOME%/axis-1_1/lib/commons-logging.jar;
%AXIS_HOME%/axis-1_1/lib/commons-discovery.jar;
%AXIS_HOME%/axis-1_1/lib/wsdl4j.jar;.
</code></pre></td></tr></tbody></table><p>关于WSDL2Java的更详细的使用，请参考Apache axis的User Guides（ <a href="http://ws.apache.org/axis/" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://ws.apache.org/axis/</a>）。 </p><p>我们这里直接使用Java编写服务端点接口的方法。在本案例中，定义了三个业务方法，它们分别是查找所有的图书、按书名查找图书、按类别查找图书。那么安照这三个业务方法，可以定义出以下的服务端点接口：</p><p>例程3 服务端点定义（BookServiceInterface.java）</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

package com.hellking.webservice.servlet;
/**
  *@author hellking
  */
import java.util.Collection;
import com.hellking.webservice.BookVO;
public interface BookServiceInterface
{
   
   /**
    * @return Vector
    */
   public Collection getAllBooks();//查找所有的图书
   
   /**
    * @param name
    * @return BookVO
    */
   public BookVO getTheBookDetail(String name);//按照书名查找图书
   
   /**
    * @return Collection
    */
   public Collection getBookByCategory(String category);//按类别查找
}
</code></pre></td></tr></tbody></table><p>上面代码中的BookVO是一个序列化的对象，它有以下属性，每个属性都提供了getter和setter方法。</p><p>例程4 BookVO的部分代码</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

public class BookVO implements java.io.Serializable
{
   private String name;
   private String publisher;
   private float price;
   private String isbn;
   private String description;
   private String category;
   private Collection authors;   
     
   public void setName(String name)
   {
     this.name=name;
   }
public String getName()
    {
     return this.name;
    }
…
}
</code></pre></td></tr></tbody></table><p>编译好这两个类。</p><p><a name="3"><span class="atitle2">服务端点描述</span></a><br /></p><p>可以使用Java2WSDL从以上定义的服务端点接口中获得服务描述（WSDL文件）。使用Apache axis工具，只要使用以下命令即可：</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

 java org.apache.axis.wsdl.Java2WSDL -o temp.wsdl 
-l"http://localhost:8080/axis/services/BookServletService"
 -n "urn:BookServletService"
 -p"com.hellking.webservice" "urn:BookServletService"
 com.hellking.webservice.servlet.BookServiceInterface
 </code></pre></td></tr></tbody></table><p>以上命令的解释：</p><pre xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">-o：生成的WSDL文件；
-l：Web服务的位置；
-n：这个WSDL文件的名字空间；
-p：包到名字空间的映射；
</pre><p>最后一个参数是Web服务端点接口。</p><p>使用以上命令后，将生成一个名为temp.wsdl Web服务描述文。</p><p><a name="4"><span class="atitle2">服务端点实现</span></a><br /></p><p>有了服务描述文件，就可以使用它来生成JAX-RPC 的框架，这个框架使得我们编程变得简单，当然您也可以直接编写实现代码，然后部署，但是那样编程会变得困难。</p><p>使用以下的命令就可以生成这个框架：</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

java org.apache.axis.wsdl.WSDL2Java -o . -d Session -s -S true 
-Nurn:BookServletService com.hellking.webservice.servlet temp.wsdl
</code></pre></td></tr></tbody></table><p>使用这个命令后将生成以下文件：</p><p>BookServiceInterface.java：新的BookServiceInterface接口，它扩展了java.rmi.Remote接口；</p><p>BookServiceInterfaceService.java：客户端服务接口，用来获得BookServiceInterface对象的引用；</p><p>BookServiceInterfaceServiceLocator.java：在客户端使用，主要用来服务定位；</p><p>BookServletServiceSoapBindingImpl.java：服务端实现类，它实现了BookServiceInterface接口，服务端的业务方法实现代码就在这里编写；</p><p>BookServletServiceSoapBindingSkeleton.java：服务端Skeleton；</p><p>BookServletServiceSoapBindingStub.java：客户端Stub；</p><p>BookVO.java：新的BookVO序列化对象；</p><p>deploy.wsdd：部署这个Web服务的脚本；</p><p>undeploy.wsdd：卸载这个Web服务的脚本。</p><p>服务端点实现类的基本框架已经生成出来了，我们的任务就是往里面增加具体的业务内容。下面我们来看具体的服务端点的实现。如例程3所示。</p><p>例程5 服务端点实现类</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

package com.hellking.webservice.servlet;
import java.util.*;
import javax.naming.*;
import com.hellking.webservice.ejb.*;

public class BookServletServiceSoapBindingImpl
 implements com.hellking.webservice.servlet.BookServiceInterface{
   InitialContext init=null;
 BookServiceFacadeHome facadeHome;
 
    public BookServletServiceSoapBindingImpl()
    {
     try
     {
      init=new InitialContext();
     }
     catch(Exception e)
     {
     }
    } 
       
   //业务方法，查找所有的图书
 public java.lang.Object[] getAllBooks() throws java.rmi.RemoteException {
             System.out.println("getAllBooks");

        try
        {
         Object objref = init.lookup("ejb/bookfacade");  
         facadeHome = (BookServiceFacadeHome)javax.rmi.PortableRemoteObject.narrow(
objref, BookServiceFacadeHome.class); 
      Collection result=facadeHome.create().getAllBook(); 
      System.out.println(result.size());
              Object[] ret=new Object[result.size()];
       Iterator it=result.iterator();
      int i=0;
      while(it.hasNext())
      {
       ret[i++]=it.next();
      } 
  // System.out.println(((BookVO)ret[0]).getName());
        return ret;   
  }
  catch(Exception e)
  {
   e.printStackTrace();
   return null;
  }  
    }
    //业务方法，按书名查找图书
    public com.hellking.webservice.BookVO getTheBookDetail(java.lang.String in0)
 throws java.rmi.RemoteException {
         com.hellking.webservice.BookVO ret=null;
        try
        {
         Object objref = init.lookup("ejb/bookfacade");  
         facadeHome = (BookServiceFacadeHome)javax.rmi.PortableRemoteObject.narrow(
objref, BookServiceFacadeHome.class); 
      Collection result=facadeHome.create().getBookDetail(in0);
      Iterator it=result.iterator();
      while(it.hasNext())
      {
       ret=( com.hellking.webservice.BookVO)it.next();
      } 

   }   
  catch(Exception e)
  {
  }  
  return ret;
    }
//业务方法，按类别查找图书
    public java.lang.Object[] getBookByCategory(java.lang.String in0)
 throws java.rmi.RemoteException {
         try
        {
         Object objref = init.lookup("ejb/bookfacade");  
         facadeHome = (BookServiceFacadeHome)javax.rmi.PortableRemoteObject.narrow(
objref, BookServiceFacadeHome.class); 
      System.out.println(in0);
      Collection result=facadeHome.create().findByCategory(in0); 
      Object[] ret=new Object[result.size()];
      Iterator it=result.iterator();
      int i=0;
      while(it.hasNext())
      {
       ret[i++]=it.next();
       System.out.println(i);
      } 
   return ret;   
  }
  catch(Exception e)
  {
   e.printStackTrace();
   return null;
  }  
 }
}
</code></pre></td></tr></tbody></table><p>可以看出，服务端点的主要任务是调用EJB组件来完成业务逻辑的。</p><p>需要向读者说明的是，为了和本系列第一篇文章中的客户端框架兼容（客户端使用的值对象是com.hellking.webservice.BookVO，而这里由WSDL2Java生成的值对象是com.hellking.webservice.servlet.BookVO）。我们需要做以下的改动：</p><p>把生成的这些代码中的com.hellking.webservice.servlet.BookVO全部改为com.hellking.webservice.BookVO，然后在Apache axis服务配置文件中申明这个BeanMapping，具体的声明方法在后面介绍。</p><p>接下来的工作是编译服务端相关的文件：BookServletServiceSoapBindingImpl、BookServletServiceSoapBindingSkeleton、BookServiceInterfaceService、BookServiceInterface。</p><p><a name="5"><span class="atitle2">服务端点部署</span></a><br /></p><p>启动服务器，这个服务器可以是任何能够运行Apache引擎Web服务器，当然最好是同时有EJB容器和EJB容器的服务器，如Webphere 、Weblogic、JBOSS，如果没有EJB容器，还需要一个额外的EJB容器，并且需要更改BookServletServiceSoapBindingImpl中获得上下文（InitialContext）的方法，如：</p><p>例程6 获得上下文环境</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

     Properties p = new Properties();   
     p.put(Context.INITIAL_CONTEXT_FACTORY, "xxxxx");
     p.put(Context.URL_PKG_PREFIXES, "xxxx");
     p.put(Context.PROVIDER_URL, "xxxx");
     init=new javax.naming.InitialContext(p);
     </code></pre></td></tr></tbody></table><p>在控制台中，转到deploy.wsdd目录下，执行以下的命令就可以完成部署：</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

 java org.apache.axis.client.AdminClient deploy.wsdd
 </code></pre></td></tr></tbody></table><p>由于我们使用的是自己的序列化Bean对象，故要在%Web-Apps%/WEB-INF/ server-config.wsdd文件中做以下更改： <br xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />找到 </p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code><service provider="java:RPC" name="BookServletService" />
…
</code></pre></td></tr></tbody></table><p>在中间加入以下内容：</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code><beanmapping xmlns:ns7="BookServletService" qname="ns7:BookServletService" languagespecifictype="java:com.hellking.webservice.BookVO" /></code></pre></td></tr></tbody></table><p>部署后您必须确保在%Web-Apps%/WEB-INF/classes目录下有服务端相关的类（BookServletServiceSoapBindingImpl、BookServletServiceSoapBindingSkeleton等）。</p><p>在浏览器里输入（这个地址您需要根据具体情况更改）：</p><p><a href="http://localhost:8080/axis/services/BookServletService?wsdl" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://localhost:8080/axis/services/BookServletService?wsdl</a></p><p>来验证Web服务是否已经部署成功，如果部署不成功，您可以先尝试重新启动服务器。</p><p><a name="6"><span class="atitle2">客户端</span></a><br /></p><p>如果服务端已经成功部署，下一步的工作就是编写客户端程序了。由于使用WSDL2Java已经生成了客户端的框架，所以我们的任务将相对简单了。</p><p>客户端编程任务主要有以下几个：</p><ul xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><li>在BookServletServiceSoapBindingStub里注册BeanMapping； 
</li><li>编写客户端业务代表，这里使用了JAXRPCDelegate； 
</li><li>更改以前的BookGUI的部分程序。 </li></ul><p><a name="7"><span class="atitle2">在BookServletServiceSoapBindingStub里注册BeanMapping</span></a><br /></p><p>由于在SOAP消息中使用了序列化的BookVO对象，故在BookServletServiceSoapBindingStub中要进行BeanMapping注册。具体方法：</p><p>找到BookServletServiceSoapBindingStub中的getAllBooks，getTheBookDetail，getBookByCategory方法，在每个方法中的</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

 java.lang.Object _resp = _call.invoke(new java.lang.Object[] {in0});
 </code></pre></td></tr></tbody></table><p>前加入以下代码：</p><p>例程7 在BookServletServiceSoapBindingStub注册BeanMapping</p><table style="WIDTH: 829px; HEIGHT: 145px" cellspacing="0" cellpadding="5" width="829" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

 QName    qn      = new QName( "BookServletService", "BookServletService" );
 _call.registerTypeMapping(com.hellking.webservice.BookVO.class, qn,                
new org.apache.axis.encoding.ser.BeanSerializerFactory(com.hellking.webservice.BookVO.class, qn),        
 new org.apache.axis.encoding.ser.BeanDeserializerFactory(com.hellking.webservice.BookVO.class, qn));
 </code></pre></td></tr></tbody></table><p>注意这里的Qname要和server-config.wsdd中描述的名称空间一致。在中server-config.wsdd，我们使用了以下的映射：</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code><beanmapping xmlns:ns7="BookServletService" qname="ns7:BookServletService" languagespecifictype="java:com.hellking.webservice.BookVO" /></code></pre></td></tr></tbody></table><p>在编写业务代表程序前，我们先来对Web服务做一个调用测试。在测试前您必须保证数据库里已经有图书信息。如果EJB和Web Application都部署好，您可以通过以下页面来往数据库里增加数据：</p><p><a href="http://localhost:8080/axis/insert_data.jsp" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://localhost:8080/axis/insert_data.jsp</a></p><p>测试代码如下：</p><p>例程8 测试Web服务</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

package com.hellking.webservice.servlet;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
import com.hellking.webservice.ejb.*;

public class Client { 
    public static void main(String[] args) {      
        try {
            
            BookServiceInterfaceServiceLocator locator=new BookServiceInterfaceServiceLocator();
            
        <span class="boldcode">BookServiceInterface myProxy=locator.getBookServletService();</span>
            Object[] c=myProxy.getAllBooks();
            com.hellking.webservice.BookVO 
book=(com.hellking.webservice.BookVO)c[0];
            System.out.println(book.getName());            
        } catch (Exception ex) {
            ex.printStackTrace();
        } 
    } 
}

      </code></pre></td></tr></tbody></table><p>如果在控制台里打印出某个图书的名字，那么就验证了客户端和服务端的部署是正确的。在进行下面的工作前，请确保这个测试是成功的。</p><p><a name="8"><span class="atitle2">编写客户端业务代表</span></a><br /></p><p>对于客户端程序来说，业务代表直接和Web服务打交道，获得Web服务返回的数据，并做对应的处理，然后把数据返回给GUI程序，GUI程序只负责数据显示。业务代表的代码如下：</p><p>例程9 JAXRPCDelegate业务代表</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

package com.hellking.webservice.servlet;

import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
import com.hellking.webservice.ejb.*;
import java.util.*;

public class JAXRPCDelegate implements com.hellking.webservice.BookBusiness
{
  BookServiceInterfaceServiceLocator locator;
     com.hellking.webservice.servlet.BookServiceInterface bookService;
     
     public JAXRPCDelegate()
  {
   try
   {
    locator=new BookServiceInterfaceServiceLocator();
          bookService=locator.getBookServletService();
         }
         catch(Exception e)
         {
         }
    }
  
 public Collection getBookByCategory(String category)
 {
     System.out.println("by_category");
  Collection ret=new ArrayList();
  try
  {   
            Object[] books=bookService.getBookByCategory(category);
            System.out.println(category);
            int i=0;
            
            while(true)
            {
             ret.add(books[i++]);
             System.out.println(i);
            }   
  }
  catch(Exception e)
  {
  }
  return ret; 
 }
 
 public Collection getAllBooks()
 {
  Collection ret=new ArrayList();
  try
  {   

            Object[] books=bookService.getAllBooks();
            int i=0;
            
            while(true)
            {
             ret.add(books[i++]);
            } 
  }
  catch(Exception e)
  {
  }
  return ret;
 }
 
 public com.hellking.webservice.BookVO getTheBookDetail(String name)
 {
  System.out.println("bookdetail");
  com.hellking.webservice.BookVO ret=new com.hellking.webservice.BookVO();
  try
  {   
           ret=bookService.getTheBookDetail(name);
  }
  catch(Exception e)
  {
  }
  return ret;  
 } 
}
</code></pre></td></tr></tbody></table><p>和第一篇文章介绍的JAXMDelegate一样，JAXRPCDelegate 同样实现了BookBusiness接口，BookBusiness接口是以前设计的接口，我们在这里进行重用，这样的好处是BookClientGUI程序几只要做很少的更改就可以运行。</p><p><a name="9"><span class="atitle2">更改以前的BookClientGUI的部分程序</span></a><br /></p><p>在BookGUI构造方法里增加以下内容：</p><p>例程10 更改BookGUI程序</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"><tbody><tr><td><pre><code>

public BookClientGUI()
{
 business=new JAXRPCDelegate();
…
}
</code></pre></td></tr></tbody></table><p>好了，经过以上的奋战，让我们来看运行的结果吧。</p><p>java com.hellking.webservice.BookClientGUI</p><p>运行结果如图4所示。</p><p><a name="N10293"><b></b></a><br /><img height="294" alt="图4 运行结果." src="http://www-128.ibm.com/developerworks/cn/webservices/ws-jax-rpc/part1/4.gif" width="543" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" /></p><p><a name="10"><span class="atitle2">总结</span></a><br /></p><p>通过以上的介绍，相信读者对JAX-RPC Web服务开发已经有一个比较深刻的认识。总结一下，使用JAX-RPC开发Web服务时，主要有以下的工作：</p><ul xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><li>服务端点定义； 
</li><li>服务描述； 
</li><li>服务端点实现； 
</li><li>服务端点部署； </li></ul><p><a name="11"><span class="atitle2">下一步</span></a><br /></p><p>本文已经介绍了把Servlet作为Web服务端点开发Web服务的全过程，下一篇将是把EJB作为Web服务端点来开发。</p><p><a name="resources"><span class="atitle2">参考资料 </span></a></p><p>Apache axis User's Guides： <a href="http://ws.apache.org/axis/" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://ws.apache.org/axis/</a> Sun jwsdp-1_1-tutorial， <a href="http://java.sun.com/webservices/downloads/webservicestutorial.html" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://java.sun.com/webservices/downloads/webservicestutorial.html</a><a href="http://www-128.ibm.com/developerworks/cn/xml/index.html" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://www.ibm.com/developerworks/cn/xml/index.html</a>XML &amp; Web services专区 JAX-RPC API <a href="http://java.sun.com/webservices" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://java.sun.com/webservices</a> Jwdp1.1 <a href="http://java.sun.com/webservices" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://java.sun.com/webservices</a> 下载 <a href="http://www-128.ibm.com/developerworks/cn/webservices/ws-jax-rpc/part1/src.zip" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">样例代码</a></p><p></p><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><a name="author1"></a><span class="atitle2">关于作者</span><br />陈亚强：北京华园天一科技有限公司高级软件工程师，擅长J2EE技术，曾参与多个J2EE项目的设计和开发，对Web服务有很大的兴趣并且有一定的项目经验。热爱学习，喜欢新技术。即将由电子工业出版社出版的《J2EE企业应用开发》正在最终定稿阶段，目前正从事J2EE方面的开发和J2EE Web服务方面的图书写作。您可以通过 <a href="mailto:cyqcims@mail.tsinghua.edu.cn" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">cyqcims@mail.tsinghua.edu.cn</a>和他联系。</td></tr></tbody></table><img src ="http://www.blogjava.net/ASONG/aggbug/54637.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ASONG/" target="_blank">汪松明</a> 2006-06-23 11:01 <a href="http://www.blogjava.net/ASONG/articles/54637.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>