程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 使用J2EE構建服務

使用J2EE構建服務

編輯:關於JAVA

如今,web services 是一門流行的實現面向服務應用的技術。J2EE已經成為一個流行的用來部署web services 應用的平台。並且,J2EE1.4制定了在Java平台上建立和部署web services應用的標准。

在這篇文章中,我將說明如何在實現了J2EE1.4規范的應用服務器之間,比如Oracle Application Server 10g,使用J2EE1.4建立可互操作的,輕便靈活的服務。

Web Services 架構

在深入研究J2EE平台上web services的開發和部署的細節之前,讓我們先簡要的查看一下web service 的架構。

Web services 有很多種定義,但是簡而言之,web services 是能夠通過網絡被發布,發現和調用的 獨立的,自我描述的組件。如圖1所示,一個web service可能會執行一個簡單的功能,比如核算銀行存款 記錄,也可能會是一個橫跨多個商業過程的復雜的任務。

圖1. 一個web service 是如何工作的

有兩種與web services 交互的方法:RPC類型和文檔類型。最初,RPC類型的web services在工業界很 流行,但是最近幾年它已經被文檔類型的web services所超越,後者被認為是在web services中交換信息 的首選方法。

RPC類型的web services提出將數據交換模擬成遠程過程調用(RPC)。這在商業應用中是很常見的。對 於遠程調用和其返回值,讓相互交換的消息都遵照一個明確定義的准則。與之相反,文檔類型的web services模擬XML文檔的交換,交換模式由發送和接收應用程序共同定義。文檔類型的服務更能適應需要 交換商業或其他類型文檔的應用程序,而且不同於RPC類型的web services,發送方不需要期望或等待一 個即時的響應。

大多數開發者一定會同意:web services是一種有效的實現SOA的技術,因為它提供了不同平台之間的 互操作性,以及依賴於XML,SOAP和HTTP等的輕量級的技術。

平台獨立性和技術實現性是web services普及的主要原因。客戶端不必了解相關技術的實現,而只需 簡單地通過網絡調用服務就可以了。例如,即使你使用Java/J2EE 技術創建了一個服務並且部署在一個 J2EE服務器上,比如Oracle Application Server Container for J2EE(OC4J),客戶端也可以使用微軟的 .NET架構創建。

既然我們已經對web services有了基本的了解,就讓我們關注一下構成web service的基本元素吧。

Web Services是由什麼構成的?

Web Services 定義語言(WSDL;發音為“wizdle”)文檔是一個web service的核心。WSDL描述了服務, 而且也是web service保證遵守的“契約”。WSDL提供了對於一個web service的完整的描述,包括端口, 操作和相關的消息類型。

這裡是WSDL文檔的一個簡單的例子,它描述了一個Hello World web service:

<definitions
 name="HelloService"
 targetNamespace="http://oracle.j2ee.ws/ejb/Hello"
 xmlns="http://schemas.xmlsoap.org/wsdl/"
 xmlns:tns="http://oracle.j2ee.ws/ejb/Hello"
 xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
 xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
 xmlns:ns1="http://oracle.j2ee.ws/ejb/Hello/types"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
 <types>
  <schema elementFormDefault="qualified"
  targetNamespace="http://oracle.j2ee.ws/ejb/Hello/types"
   xmlns="http://www.w3.org/2001/XMLSchema"
   xmlns:soap11-enc="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:tns="http://oracle.j2ee.ws/ejb/Hello/types"
   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <complexType name="sayHello">
    <message name="HelloServiceInf_sayHello">
      <part name="parameters"
        element="ns1:sayHelloElement"/>
    </message>
    <message name="HelloServiceInf_sayHelloResponse">
      <part name="parameters"
        element="ns1:sayHelloResponseElement"/>
    </message>
    <portType name="HelloServiceInf">
      <operation name="sayHello">
        <input message="tns:HelloServiceInf_sayHello"/>
        <output message="tns:HelloServiceInf_sayHelloResponse"/>
      </operation>
    </portType>
    <sequence>
      <element name="String_1" nillable="true" type="string"/>
    </sequence>
  </complexType>
  <complexType name="sayHelloResponse">
    <sequence>
    <element name="result" nillable="true" type="string"/>
    </sequence>
  </complexType>
  <element name="sayHelloElement" type="tns:sayHello"/>
  <element name="sayHelloResponseElement"
    type="tns:sayHelloResponse"/>
  </schema>
 </types>
 <binding name="HttpSoap11Binding" type="tns:HelloServiceInf">
 <soap:binding style="document"
      transport="http://schemas.xmlsoap.org/soap/http"/>
 <operation name="sayHello">
   <soap:operation
      soapAction="http://oracle.j2ee.ws/ejb/Hello:sayHello"/>
   <input>
     <soap:body use="literal" parts="parameters"/>
   </input>
   <output>
     <soap:body use="literal" parts="parameters"/>
   </output>
 </operation>
 </binding>
 <service name="HelloService">
   <port name="HttpSoap11" binding="tns:HttpSoap11Binding">
     <soap:address location="REPLACE_WITH_ACTUAL_URL"/>
   </port>
</service>
</definitions>

如果你觀察這個WSDL,你會注意到它有一個對於HelloService web service的完整的描述,包括端口 ,操作和消息類型。WSDL是web service和它的客戶之間的合約,並且它能夠幫助自動生成客戶代理。

Web services平台的另外兩項關鍵技術是SOAP,被用來調用web service的協議,和UDDI,它提供了用 來定位web services 的注冊器。

對於這些技術的支持已經完全被集成到J2EE平台中了。讓我們關注一下J2EE對於web services的支持 。

使用J2EE作為Web Services的平台

J2EE 1.4為使用常規Java類或企業級Java Beans來創建和部署web services提供了一個全面的平台。 以下表格給出了J2EE 1.4中包括的web service APIs的細節。

定義在Java Community Process的JSR 101之下的JAX-RPC,提供了創建和訪問web services的Java API,因此它是使用J2EE平台創建和部署web services的“心髒和靈魂”。通過向應用程序開發者隱藏XML 類型和Java類型映射的復雜性,以及處理XML和SOAP消息的底層細節,它提供了一個簡單的,健壯的創建 web services應用的平台。為了引入一個方法調用范式,它提供了兩種編程模式:服務器端模式,使用 Java類或無狀態EJB開發web service 端點,和客戶端模式,創建作為本地對象訪問web services的Java 客戶端。JAX-RPC 1.1要求使用SOAP 1.1,並且實現與使用其他技術創建的web services之間的互操作性 ,比如微軟的.NET。實現了J2EE1.4規范的應用服務器,比如OC4J 10.1.3和SUN的Java System Application Sever,提供了對於JAX-RPC的支持。

JAX-RPC的叫法有點用詞不當,因為它既支持RPC類型的web services,也支持文檔類型的web services。

Web Services部署模型

在J2EE 1.4之前,所有J2EE商家都使用他們私有的部署模型支持web services。J2EE 1.4為Java Web Services定義了部署模型。它為J2EE平台上的web services制定了開發,部署以及服務發布和使用的標准 。

有了J2EE 1.4對web services的支持,讓我們學習使用J2EE平台來建造web service的方法。

使用J2EE創建一個Web Service

把web service創建成一個輕便的和可互操作的分布式組件不是一項瑣碎的任務。如之前討論的,你既 可以把常規Java類,也可以把無狀態EJB部署成web services。常規Java類被打包在一個web模塊中,而 EJB web services被打包在標准的ejb-jar模塊中。

在這兩種部署選擇中,你會使用哪一個呢?

Java 類對無狀態EJB:永無止境的爭論

你會選擇常規Java類還是EJB作為你創建web service的技術可能是一個長期的爭論。Java類比EJB更容 易開發,它是純的Java對象,並且它不具有EJB帶來的“額外辎重”。但是,EJB提供了幾個很好的特點, 比如被聲明的事務和安全性,因此它使開發者將精力集中於建立商業邏輯,而不需要擔心基礎服務架構。 EJB 3.0大大簡化了設計模型,在它的規范中,EJB看起來就像常規Java類。

打包要求

無論你決定使用常規Java類還是EJB,你都必須把一些定義文件打包到你的WAR或ejb-jar中,這樣你才 能將你的組件作為Java web service展示出來。下面是分別基於EJB和Java類的web service的打包結 構:

基於EJB 的web service的ejb-jar:

/META-INF/
ejb-jar.xml
webservices.xml
oracle-webservices.xml
mapping-file.xml
wsdl/ wsdl 文件
ejb classes (包括端點和bean類)

常規Java web service的web 應用(.war)

/WEB-INF/
web.xml
webservices.xml
oracle-webservices.xml
mapping-file.xml
wsdl/ the wsdl 文件
/classes/(包括端點和bean類)
/lib/

讓我們討論每一個部署時的定義文件和描述符:

WSDL:如前所描述。

端點接口:web service端點必須實現java.rmi.Remote接口,並且在端點接口中的每一個方法都必須拋 出java.rmi.RemoteException異常。這個端點需要注冊到模塊(ejb-jar.xml或web.xml)的標准部署描述符 中。你的部署描述符(比如,ejb-jar.xml)需要包括如下條目:

<service-endpoint>

oracle.ejb21.ws.HelloServiceInf

</service-endpoint>

如下是一個Hello World web service的端點的代碼:

public interface HelloServiceInf
                 extends java.rmi.Remote {
java.lang.String sayHello(java.lang.String name)
                    throws java.rmi.RemoteException;
}

Web service部署描述符:J2EE平台需要一個名叫webservices.xml的部署描述符。它指定了部署到J2EE 應用服務器所需的全部web service描述符,以及它們與容器資源和服務的依賴關系。同時,它還指定 了:WSDL的位置;mapping.xml,它包含了Java到WSDL的映射;和Hello World web service的服務端點接口 。在Resources章節中給出了一個與示例代碼打包在一起的webservices.xml的例子。

商家規范部署描述符:一些實現規范參考,比如上下文根目錄和端點地址,不能在web service部署描 述符中指定。取而代之,你應該在商家規范部署描述符中指定它們。例如,如果你正使用OC4J,你將需要 在WAR或ejb-jar中打包一個oracle-webservices.xml文件來定義那些屬性。

Java-WSDL映射:這個文件定義了WSDL和Java類間的映射。映射文件沒有標准的名字;web services部署 描述符決定了它的名字。

在把你的組件部署為web service之前,你必須把所有的定義文件打包到WAR或ejb-jar模塊中。有很多 開發工具,比如Oracle JDeveloper,通過完成平凡的任務,比如生成部署描述符,映射文件等,簡化了 web service的開發。此外,大多數應用服務器都提供了web services裝配工具,它們能夠滿足J2EE web service的打包要求。

除了理解組成一個web service的組件和相關的打包要求外,還有一些在你開發web service時必須解 決的架構問題。

構建服務的途徑

創建一個web service時的主要挑戰是為服務確定合適的粒度。你可以新建一個服務,也可以展示一個 由Java類或EJB創建的已經存在的組件並把它發布為一個服務。當創建服務的時候,你可以使用自頂向下 方法或自底向上方法:

自底向上方法:這個方法允許把一個現有的Java類或EJB發布為web service。這是很流行的創建服務的 方法,因為它使你不必重寫應用程序,而是重用你現有的商業邏輯。如果你使用這種方法,你必須為你的 web service實現添加一個web service端點接口,同時創建一個WSDL,它同其他部署描述符一樣用來描述 web service。由應用服務器提供的工具,比如Oracle Application Server的web service裝配工具,通 過生成WSDL,webservices.xml等描述符以及web services組件的映射文件使您的開發生活更加簡單―― 這把開發者從手工創造那些文件的痛苦中解放了出來。

自頂向下方法:這是創建服務的“純粹”的方法,它更適合於當你根據草稿創建服務的時候。你從使用 WSDL來描述服務開始,而不是直接跳入到實現。這個方法比自底向上方法更優越,因為在開發web service的同時,由於對操作,信息和對WSDL的控制的仔細考慮,使得服務更容易使用,更可維護和更可 互操作。一些J2EE廠商提供了工具使這種方法變得更容易,例如,Oracle Application Server的web services裝配器能夠生成接口,部署描述符以及你用來創建應用程序的類框架。

互操作問題

顯然,你的web services在本質上的可互操作性是必要的。J2EE 1.4要求與Basic Profile 1.0(由Web Services:Interoperability(WS-I)機構指定)保持一致。當創建web services時,你必須在將它們部署到 產品中之前測試它們的互操作性。

除了設計方法和服務互操作的需要,你可以遵循一些最優方法來使你的web service效用最大化。

最佳實踐

這裡有一些開發web services的最優方法:

避免在你的應用程序中過度使用web services。檢查你是否真的需要把你的應用程序發布為web service。

服務的模塊性是很重要的。使用一個粗粒度的web service;例如:一個會話把你的商業邏輯封裝為web service。

確定你設計了你的web service,以使它制造最少的網絡通信量。

遵循WS-I基礎框架。使用JAX-RPC數據類型作為調用你的web service的方法的參數,這樣可以使它具 有與異類web services的互操作性。如果互操作性對於你的應用程序來說很重要,那麼請避免使用 Collection,HashMap和List之類的數據類型作為你的web service的參數。

許多對於J2EE應用的傳統最優方法也同樣適用於web services。比如,避免把一個包含長時間事務的 組件發布為web service。

權衡你的web service的安全需求和性能,因為安全性需要更高的開銷。一個端到端安全的web service所需的性能開銷是很高的。

J2EE藍圖應用軟件Java Adventure Builder提供了一個很優秀的用來創建基於Java 的web services 應用的工具。

一旦一個web service完成了設計,開發和部署,那麼能與之提供的服務相交互的客戶端組件也會被隨 之創建。

調用 Web Services

一個web service的客戶端可以是如下的任意一種:靜態樁,動態代理或者動態調用接口(DII)。

創建一個web service客戶端可能跟創建一個簡單的web service一樣復雜。幸運的是,J2EE 1.4為開 發者簡化了這一過程,你可以通過任何J2EE組件(即web客戶端或EJB組件)來使用web services。

通過如下過程,你可以像使用JNDI訪問其他任何資源一樣來調用web service:

在你的組件的部署描述符中定義一個service-ref元素。例如,如果你從一個web模塊來訪問 HelloWorldService web service,那麼該模塊的web.xml文件應該包含如下:

<service-ref>
<service-ref-name>service/HelloWorldService</service-ref-name>
<service-interface>oracle.ws.HelloWorldService</service-interface>
<wsdl-file>META-INF/HelloWorldService.wsdl</wsdl-file>
<service-qname>urn:oracle-ws</service-qname>
</service-ref>

為了使你的應用程序能夠找到web service,你必須在你的商家規范部署描述符中指定web service 的 位置。例如,如果你使用OC4J從你的網絡模塊來查詢web service,你的商家規范網絡描述符orion- web.xml必須包含如下內容:

<service-ref-mapping name="service/HelloWorldService">
    <port-info>
      <wsdl-port namespaceURI="urn: HelloWorldService"
                         localpart="HelloWorldServicePort"/>
    <stub-property>
         <name>javax.xml.rpc.service.endpoint.address</name>
         <value>http://localhost:8888/hello/HelloWorldInf</value>
    </stub-property>
   </port-info>
</service-ref-mapping>

在你的服務器中進行部署之前,你必須把端點接口和類文件打包到你的應用程序中。你可以通過JNDI 查找來使用web service:

InitialContext ctx= new InitialContext();
HelloServiceInf hs = (HelloServiceInf)
             ctx.lookup("java:comp/env/service/HelloWorldService");
HelloWorld hello= hs.getHelloWorldServicePort();
String myhello = hs.sayHello("Debu Panda") ;

Java Web Services 的未來

正在形成的Web Services標准的推廣

Web services平台已經成長為具有可靠性,安全性,事務性,易管理性,政策性等特性的平台。在web services領域有相當一部分已經出現或正在出現的標准。為了設計一套全新的Java API來推廣那些正在形 成的標准,在Java Community Process中有一些JSR正在完成中,下表列出了其中的一些JSR:

除了那些正在進化的標准,我們現在來領略一下下一代J2EE平台的主要版本對於web services的支持 。

使用J2EE 5.0簡化SOA的開發

使用J2EE創建面向服務的應用程序確實很困難,因此通過使用由JSR 181定義的Web Services 元數據 注解,J2EE 5.0將使開發更簡單。EJB 3.0和Web Services元數據具有相似的目標,就是向開發者提供親 和力。

為了在J2EE 1.4中開發一個簡單的Java web service,你需要幾個web service定義文件:WSDL,映射 文件和幾個冗長的標准以及私有的web services部署描述符。Web Services元數據規范使用一種類似於 EJB 3.0的缺省配置方法來使開發更簡便。Web Services元數據注解處理器(或web services 裝配工具)會 為你生成這些文件,因此你只需要關心類的實現。

當你使用Web Services元數據開發時,這是一個看起來如此簡單的Java web service:

package oracle.jr181.demo;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService(name = "HelloWorldService",
      targetNamespace = "http://hello/targetNamespace" )
public class HelloWorldService {       
@WebMethod public String sayhello(String name ) {
     return "Hello” +name+ “ from jws";
    }
}

正如我之前提到的,EJB 3.0使用常規Java類簡化了EJB的開發。通過利用EJB 3.0和Web Services元數 據,開發基於EJB的web services將會變得越來越簡單。當使用EJB 3.0和web services元數據時,這是一 個看起來如此簡單的HelloWorld EJB web service。你不必擔心創建WSDL,部署描述符等等,應用服務器 會在部署過程中生成這些定義文件。

package oracle.ejb30.ws;
import javax.ejb.Remote;
import javax.jws.WebService;
@WebService 
public interface HelloServiceInf extends java.rmi.Remote{
@WebMethod java.lang.String sayHello(java.lang.String name)
                              throws java.rmi.RemoteException;
}

如下是EJB 3.0中 HelloWorld EJB的實現類:

package oracle.ejb30.ws;
import java.rmi.RemoteException;
import javax.ejb.Stateless;
@Stateless(name="HelloServiceEJB")
public class HelloServiceBean implements HelloServiceInf {
public String sayHello(String name) {
 return("Hello "+name +" from first EJB3.0 Web Service");
 }
}

以上例子清楚的表明了通過使用web services元數據和EJB 3.0,服務開發正在變得越來越簡單。

總結

在這篇文章中,你學習了使用J2EE平台創建web services的基礎知識。現在,你可以在你最喜歡的實 現了J2EE規范的應用服務中,比如Oracle Application Server 10g,Sun Java System Application Server等,開始創建和部署你的web services了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved