<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 1, 文章 - 44, 評論 - 2, 引用 - 0
    數據加載中……

    用JAX-RPC開發Web服務: Servlet作為Web服務端點

    關鍵詞JAX-RPC ?? web服務 ?? ??????????????????????????????????????

    閱讀本文前您需要以下的知識和工具:

    • JavaTM Web Services Developer Pack 1.1,并且會使用初步使用;
    • 遼倩崾褂靡恢諩JB容器來開發、部署EJB,并且了解怎么在客戶端訪問EJB組件;
    • 對Apache axis Web服務開發工具有基本的了解;
    • 基本的Java編程知識。

    如果使用JAX-RPC開發Web服務,我們幾種選擇:

    • Servlet作為Web服務端點;
    • 無狀態會話Bean作為Web服務端點;
    • 基于消息(如JMS)的應用程序作為Web服務端點。

    本文以Servlet作為Web服務端點的情況來介紹JAX-RPC Web服務開發,關于本篇文章中案例的介紹詳見本系列文章第一篇: 《用JAXM開發Web服務》

    本文的參考資料見 參考資料

    本文的全部代碼在這里 下載

    JAX-RPC快速入門

    JAX-RPC,Java? API for XMLbased RPC,顧名思義,它是一種遠程方法調用(或者說遠程過程調用),那么它和其它的遠程方法調用(RPC, COM,CORBA,RMI)有什么區別呢?我們看一般的遠程方法調用的結構,如圖1所示。


    圖1 遠程方法調用

    綜合比較常用的遠程方法調用技術,它們有以下的共性:

    • 在客戶端和服務端有通用編程接口;
    • 在客戶端有Stub,在服務端有Tie(有的叫Skeleton);
    • 客戶端和服務端有專門的協議進行數據傳輸。

    對于通用接口的描述,比如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傳輸協議之上。

    JAX-RPC的構架如下。


    圖2 JAX-RPC 的構架

    從上圖可以看出,客戶端調用的是JAX-RPC服務端點(Service Endpoint),這個服務端點是通過WSDL語言描述的。在這個體系結構中,對于客戶端,可以是JS2E、J2ME或者J2EE平臺運行環境;對于服務端,可以是J2EE1.3或者J2EE1.4容器(Servlet容器或者EJB容器)。Apache axis是一個很好的JAX-RPC運行環境實現,同時也提供了優秀的開發工具,本文將使用它進行開發。

    使用Servlet作為服務端點,本案例的基本構架如下圖所示。


    圖3 案例的基本構架

    客戶端通過SOAP消息和JAX-RPC服務端交互,JAX-RPC服務端運行在Servlet容器中,它通過調用EJB容器中的EJB組件來處理具體的業務邏輯。

    使用JAX-RPC開發Web服務,可以按照以下的步驟進行:

    1. 服務端點定義;
    2. 服務描述;
    3. 服務端點實現;
    4. 服務端點部署;
    5. 服務發布和發現。

    注意:對于服務的發布和發現,由于機制比較復雜,本文不討論,可能會在本系列文章進行專題討論。

    開發快速入門

    一個完整的JAX-RPC開發實例,將按照上面的5個步驟進行,但是我們也可以使用非常簡單的方式來發布一個Web服務。在介紹我們的案例前,讓我們用一分鐘快速開發一個Web服務。

    首先安裝好JWSDP,你可以從 http://java.sun.com/webservices下載。

    把本案例源代碼中的\src\bookservice.ear\web.war目錄拷貝到%JWSDP_HOME%\webapps目錄下,web.war文件里已經包括了Apache axis運行環境。

    在%JWSDP_HOME%\classes目錄下新建一個HelloWorld.java文件,它的代碼如下:

    例程1 最簡單的Web服務HelloWorld

    
    
    package com.hellking.webservice;
    public class HelloWorld
    {
     public String sayHello(String name)
     {
      return "Hello! "+name;
     }
    }
    

    編譯這個類,然后編輯%JWSDP_HOME%\webapps\WEB-INF\server-config.wsdd文件,找到記,在其后面加入以下內容:

    在瀏覽器例輸入:

    http://localhost:8080/web/services/HelloWorld?wsdl

    如果出現部署WSDL描述文件,那么最簡單的Web服務已經部署成功!

    下面我們使用最簡單的方式來調用這個Web服務,在瀏覽器里輸入:

    http://localhost:8080/web/services/HelloWorld?wsdl&method=sayHello&name=hellking

    那么在瀏覽器將會顯示以下內容:

    例程2 在瀏覽器里調用Web服務

    Hello! hellking

    如果結果是這樣,那么最簡單的Web服務已經部署成功,并且測試也通過了。注意"Hello!hellking"是調用Web服務返回的結果,它是我們期望的。下面我們來看一個完整的Web服務開發的例子。

    服務端點定義

    服務端點定義的工作主要是確定"服務定義接口"(Service Definition Interface),有時也叫Web服務端點接口(Web services endpoint interface)。服務端點定義有兩中方法獲得:

    • 使用某些工具從WSDL文件獲得;
    • 直接使用Java語言編寫。

    Apache axis提供了從WSDL文件中獲得Web服務端點的工具。您可以這樣使用:

    
    
    java org.apache.axis.wsdl.WSDL2Java (WSDL-file-URL)
    

    使用這個命令前先設置好以下的環境變量,后面的介紹中還會使用axis工具,它們也要這樣設置環境變量:

    
    
    SET AXIS_HOME=
    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;.
    

    關于WSDL2Java的更詳細的使用,請參考Apache axis的User Guides( http://ws.apache.org/axis/)。

    我們這里直接使用Java編寫服務端點接口的方法。在本案例中,定義了三個業務方法,它們分別是查找所有的圖書、按書名查找圖書、按類別查找圖書。那么安照這三個業務方法,可以定義出以下的服務端點接口:

    例程3 服務端點定義(BookServiceInterface.java)

    
    
    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);//按類別查找
    }
    

    上面代碼中的BookVO是一個序列化的對象,它有以下屬性,每個屬性都提供了getter和setter方法。

    例程4 BookVO的部分代碼

    
    
    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;
        }
    …
    }
    

    編譯好這兩個類。

    服務端點描述

    可以使用Java2WSDL從以上定義的服務端點接口中獲得服務描述(WSDL文件)。使用Apache axis工具,只要使用以下命令即可:

    
    
     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
     

    以上命令的解釋:

    -o:生成的WSDL文件;
    -l:Web服務的位置;
    -n:這個WSDL文件的名字空間;
    -p:包到名字空間的映射;
    

    最后一個參數是Web服務端點接口。

    使用以上命令后,將生成一個名為temp.wsdl Web服務描述文。

    服務端點實現

    有了服務描述文件,就可以使用它來生成JAX-RPC 的框架,這個框架使得我們編程變得簡單,當然您也可以直接編寫實現代碼,然后部署,但是那樣編程會變得困難。

    使用以下的命令就可以生成這個框架:

    
    
    java org.apache.axis.wsdl.WSDL2Java -o . -d Session -s -S true 
    -Nurn:BookServletService com.hellking.webservice.servlet temp.wsdl
    

    使用這個命令后將生成以下文件:

    BookServiceInterface.java:新的BookServiceInterface接口,它擴展了java.rmi.Remote接口;

    BookServiceInterfaceService.java:客戶端服務接口,用來獲得BookServiceInterface對象的引用;

    BookServiceInterfaceServiceLocator.java:在客戶端使用,主要用來服務定位;

    BookServletServiceSoapBindingImpl.java:服務端實現類,它實現了BookServiceInterface接口,服務端的業務方法實現代碼就在這里編寫;

    BookServletServiceSoapBindingSkeleton.java:服務端Skeleton;

    BookServletServiceSoapBindingStub.java:客戶端Stub;

    BookVO.java:新的BookVO序列化對象;

    deploy.wsdd:部署這個Web服務的腳本;

    undeploy.wsdd:卸載這個Web服務的腳本。

    服務端點實現類的基本框架已經生成出來了,我們的任務就是往里面增加具體的業務內容。下面我們來看具體的服務端點的實現。如例程3所示。

    例程5 服務端點實現類

    
    
    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;
      }  
     }
    }
    

    可以看出,服務端點的主要任務是調用EJB組件來完成業務邏輯的。

    需要向讀者說明的是,為了和本系列第一篇文章中的客戶端框架兼容(客戶端使用的值對象是com.hellking.webservice.BookVO,而這里由WSDL2Java生成的值對象是com.hellking.webservice.servlet.BookVO)。我們需要做以下的改動:

    把生成的這些代碼中的com.hellking.webservice.servlet.BookVO全部改為com.hellking.webservice.BookVO,然后在Apache axis服務配置文件中申明這個BeanMapping,具體的聲明方法在后面介紹。

    接下來的工作是編譯服務端相關的文件:BookServletServiceSoapBindingImpl、BookServletServiceSoapBindingSkeleton、BookServiceInterfaceService、BookServiceInterface。

    服務端點部署

    啟動服務器,這個服務器可以是任何能夠運行Apache引擎Web服務器,當然最好是同時有EJB容器和EJB容器的服務器,如Webphere 、Weblogic、JBOSS,如果沒有EJB容器,還需要一個額外的EJB容器,并且需要更改BookServletServiceSoapBindingImpl中獲得上下文(InitialContext)的方法,如:

    例程6 獲得上下文環境

    
    
         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);
         

    在控制臺中,轉到deploy.wsdd目錄下,執行以下的命令就可以完成部署:

    
    
     java org.apache.axis.client.AdminClient deploy.wsdd
     

    由于我們使用的是自己的序列化Bean對象,故要在%Web-Apps%/WEB-INF/ server-config.wsdd文件中做以下更改:
    找到

    在中間加入以下內容:

    部署后您必須確保在%Web-Apps%/WEB-INF/classes目錄下有服務端相關的類(BookServletServiceSoapBindingImpl、BookServletServiceSoapBindingSkeleton等)。

    在瀏覽器里輸入(這個地址您需要根據具體情況更改):

    http://localhost:8080/axis/services/BookServletService?wsdl

    來驗證Web服務是否已經部署成功,如果部署不成功,您可以先嘗試重新啟動服務器。

    客戶端

    如果服務端已經成功部署,下一步的工作就是編寫客戶端程序了。由于使用WSDL2Java已經生成了客戶端的框架,所以我們的任務將相對簡單了。

    客戶端編程任務主要有以下幾個:

    • 在BookServletServiceSoapBindingStub里注冊BeanMapping;
    • 編寫客戶端業務代表,這里使用了JAXRPCDelegate;
    • 更改以前的BookGUI的部分程序。

    在BookServletServiceSoapBindingStub里注冊BeanMapping

    由于在SOAP消息中使用了序列化的BookVO對象,故在BookServletServiceSoapBindingStub中要進行BeanMapping注冊。具體方法:

    找到BookServletServiceSoapBindingStub中的getAllBooks,getTheBookDetail,getBookByCategory方法,在每個方法中的

    
    
     java.lang.Object _resp = _call.invoke(new java.lang.Object[] {in0});
     

    前加入以下代碼:

    例程7 在BookServletServiceSoapBindingStub注冊BeanMapping

    
    
     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));
     

    注意這里的Qname要和server-config.wsdd中描述的名稱空間一致。在中server-config.wsdd,我們使用了以下的映射:

    在編寫業務代表程序前,我們先來對Web服務做一個調用測試。在測試前您必須保證數據庫里已經有圖書信息。如果EJB和Web Application都部署好,您可以通過以下頁面來往數據庫里增加數據:

    http://localhost:8080/axis/insert_data.jsp

    測試代碼如下:

    例程8 測試Web服務

    
    
    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();
                
            BookServiceInterface myProxy=locator.getBookServletService();
                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();
            } 
        } 
    }
    
          

    如果在控制臺里打印出某個圖書的名字,那么就驗證了客戶端和服務端的部署是正確的。在進行下面的工作前,請確保這個測試是成功的。

    編寫客戶端業務代表

    對于客戶端程序來說,業務代表直接和Web服務打交道,獲得Web服務返回的數據,并做對應的處理,然后把數據返回給GUI程序,GUI程序只負責數據顯示。業務代表的代碼如下:

    例程9 JAXRPCDelegate業務代表

    
    
    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;  
     } 
    }
    

    和第一篇文章介紹的JAXMDelegate一樣,JAXRPCDelegate 同樣實現了BookBusiness接口,BookBusiness接口是以前設計的接口,我們在這里進行重用,這樣的好處是BookClientGUI程序幾只要做很少的更改就可以運行。

    更改以前的BookClientGUI的部分程序

    在BookGUI構造方法里增加以下內容:

    例程10 更改BookGUI程序

    
    
    public BookClientGUI()
    {
     business=new JAXRPCDelegate();
    …
    }
    

    好了,經過以上的奮戰,讓我們來看運行的結果吧。

    java com.hellking.webservice.BookClientGUI

    運行結果如圖4所示。


    圖4 運行結果.

    總結

    通過以上的介紹,相信讀者對JAX-RPC Web服務開發已經有一個比較深刻的認識。總結一下,使用JAX-RPC開發Web服務時,主要有以下的工作:

    • 服務端點定義;
    • 服務描述;
    • 服務端點實現;
    • 服務端點部署;

    下一步

    本文已經介紹了把Servlet作為Web服務端點開發Web服務的全過程,下一篇將是把EJB作為Web服務端點來開發。

    參考資料

    Apache axis User's Guides: http://ws.apache.org/axis/ Sun jwsdp-1_1-tutorial, http://java.sun.com/webservices/downloads/webservicestutorial.htmlhttp://www.ibm.com/developerworks/cn/xml/index.htmlXML & Web services專區 JAX-RPC API http://java.sun.com/webservices Jwdp1.1 http://java.sun.com/webservices 下載 樣例代碼

    關于作者
    陳亞強:北京華園天一科技有限公司高級軟件工程師,擅長J2EE技術,曾參與多個J2EE項目的設計和開發,對Web服務有很大的興趣并且有一定的項目經驗。熱愛學習,喜歡新技術。即將由電子工業出版社出版的《J2EE企業應用開發》正在最終定稿階段,目前正從事J2EE方面的開發和J2EE Web服務方面的圖書寫作。您可以通過 cyqcims@mail.tsinghua.edu.cn和他聯系。

    posted on 2006-06-23 11:01 ASONG 閱讀(294) 評論(0)  編輯  收藏 所屬分類: webservice


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 精品特级一级毛片免费观看| 亚洲高清日韩精品第一区| 四虎亚洲精品高清在线观看| 182tv免费视视频线路一二三 | 久久久精品午夜免费不卡| 国产日产亚洲系列| 免费看无码特级毛片| 亚洲国产精品va在线播放| 午夜无码A级毛片免费视频| 亚洲国产精品线在线观看| 最近2019中文字幕免费直播 | 33333在线亚洲| 性做久久久久久久免费看| 亚洲色成人四虎在线观看| 国产大片91精品免费观看男同| 美女羞羞喷液视频免费| 亚洲综合伊人久久大杳蕉| 久久国产免费一区| 亚洲91精品麻豆国产系列在线| 暖暖免费高清日本中文| 人成电影网在线观看免费| 亚洲国产人成在线观看| 欧美最猛性xxxxx免费| 亚洲AV无码专区在线厂| 亚洲乱亚洲乱妇无码麻豆| 19禁啪啪无遮挡免费网站| 亚洲精品中文字幕无码A片老| 午夜亚洲av永久无码精品 | 日本视频免费观看| 亚洲国产精品无码AAA片| 91人成网站色www免费下载| 亚洲中文字幕AV在天堂| 亚洲午夜福利精品无码| 久久久精品2019免费观看| 亚洲色少妇熟女11p| 亚洲综合无码AV一区二区| 日韩不卡免费视频| CAOPORM国产精品视频免费| 亚洲欧洲国产成人精品| 成人伊人亚洲人综合网站222| 99久久免费精品高清特色大片|