EJB3.0介紹

Enterprice JavaBeans是一個用於分佈式業務應用的標準服務端組件模型。採用Enterprice JavaBeans架構編寫的應用是可伸縮的、事務性的、多用戶安全的。

採用ejb編寫的這些應用,可以部署在任何支持Enterprice JavaBeans規範的服務器平臺,如jbossweblogic等。

EJB實際上是用於編寫業務層代碼。我們知道一個基於MVC結構的應用應包含顯示層、控制層和業務層, 假設我們採用ejb開發基於MVC結構的應用,那麼ejb就是用於開發應用的業務層.

EJB最大的特點是分佈式,EJBs都是業務層的東西,對於多個顯示層可以做到業務層完全不用改變。我們寫的EJBs發佈到EJB容器比如JBOSS中,客戶端(普通Java應用或者JavaWeb應用)通過JNDI找到你的EJB,這中間通過socket通信,爲了降低這種消耗,可以定義本地的EJB,但是這個EJB必須和你的客戶端在同一個JVM中,即一個JBoss中,比如你的JavaWeb發佈到這個JBoss中。


EJB爲我們提供了很多在企業開發中需要使用到的服務,如事務管理/安全/持久化/分佈式等,因爲這些服務由容器提供,無需我們自行開發,這樣大大減少了我們的開發工作量.另外EJB提供了強制式分層解耦設計方法

EJB3.0運行環境

EJB3.0應用需要運行在JDK1.5以上版本。

進入http://java.sun.com/javase/downloads/index_jdk5.jsp下載JDK。在頁面中找到JDK5.0 Update 16(版本在不斷更新中,有可能大於16),點擊右邊的Download

按照安裝嚮導提示安裝,安裝路徑選擇C:\Java\jdk1.5.0_16Jdk安裝完後,接着問你是否安裝jre,也一起安裝上。

右鍵點擊“我的電腦”->“屬性”->“高級”->“環境變量”,在“系統變量”裏添加JAVA_HOME變量,值爲JDK的安裝路徑,如:C:\Java\jdk1.5.0_16

在“系統變量”裏再添加CLASSPATH變量,值爲:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;

在系統變量欄找到變量名爲Path的選項,點“編輯”在變量值的末尾添加;%JAVA_HOME%\bin;

EJB3.0應用需要運行在EJB容器裏,下面是一些JavaEE應用服務器,JavaEE應用服務器包含Web容器和EJB容器。

lJboss4.2.x以上版本)

 是一個成熟的開源的準JavaEE應用服務器,在開源JavaEE應用服務器中所佔市場份額第一。如果你打算選用開源的JavaEE應用服務器,那麼jboss是最值得選擇的。

lGlassfish

 是一個開源的JavaEE應用服務器,對JavaEE規範的支持非常好,其運行性能比較高。因爲發展時間相對較短,市場佔有率比較低。另外,它能否提供穩定的運行性能,還有待時間的考驗。

lWeblogic10以上版本)

 是商業市場佔有率第一的商業JavaEE應用服務器,它具有出色的穩定性,並提供了人性化的管理界面,還有企業需要使用到的衆多功能。

lSun ApplicationServer9.0以上版本)

 商業JavaEE應用服務器,如果你打算選用商業應用服務器運行ejb3,這個是不錯的選擇。

lOracle ApplicationServer10g以上版本)

 商業JavaEE應用服務器,如果你的數據庫Oracle,要想兼容性更好,這個是不錯的選擇。

lapusic應用服務器

 這是國內的商業JavaEE應用服務器,主要在政府中佔有一定的市場份額。但是其向開發人員提供的文檔實在太少了。

注意:Tomcat目前只是Web容器,它不能運行EJB應用。

進入http://labs.jboss.com/jbossas/downloads/下載頁面,選擇jboss4.2.3.GA下載(大小爲95MB),如果你安裝的jdk是1.5版本,請選擇jboss-4.2.3.GA.zip文件下載。如果你安裝的jdk是1.6版本,請選擇jboss-4.2.3.GA-jdk6.zip文件下載。下載後直接解壓縮文件即可完成安裝,爲了避免應用出現莫名的錯誤,解壓縮的路徑最好不要帶有空格和中文,如“Program Files”。

進入jbossbin目錄,找到啓動腳本run.bat。雙擊run.bat即可啓動jboss,此時啓動的配置項爲default

       如果啓動出錯,請檢查下列情況:

  1.端口是否被佔用,如:80801099

  2是否爲JDK設置的JAVA_HOMEClassPath系統變量,如果沒有,請按照前面視頻介紹的方法設置。

  3.檢查jboss所用的jdk是否1.5以上版本,這些信息可以在jboss的控制檯觀察到。

       4.如果啓動時出現這樣的錯誤:“findstr不是內部或外部命令,也不是可運行的程序或批處理文件”。那麼應該在系統變量Path中追加“%SystemRoot%\system32;%SystemRoot%;

      

       最後的辦法是重裝機器上的JDK,祝你好運。
l因爲在後面的學習中,我們需要使用到系統變量JBOSS_HOME,它指向jboss的安裝路徑。所以安裝完後我們需要添加該變量,方法是:右鍵點擊“我的電腦”->屬性”->高級”->環境變量”,在“系統變量”裏添加JBOSS_HOME變量,值爲Jboss的安裝路徑,如:D:\JavaEEServer\jboss
l爲了方便輸入jboss的命令,我們把jbossbin目錄添加到系統路徑裏。在系統變量一欄找到變量名爲Path的選項,點“編輯”在變量值的末尾添加:;%JBOSS_HOME%\bin;
開發EJB依賴的jar文件

 可以在jboss安裝路徑的client目錄下找到,通常會把client目錄下的所有jar文件添加到項目的類路徑下.


EJB中的三種bean

1.會話bean(session bean)

  負責與客戶端交互,是編寫業務邏輯的地方,在會話bean中可以通過jdbc直接操作數據庫,但大多數情況下都是通過實體bean來完成對數據庫的操作.

2.實體bean(entity bean)

  它實際上屬於java持久化規範(簡稱JPA)裏的技術,JPA的出現主要是爲了簡化現有的持久化開發工作和整合ORM技術,結束現在hibernateTopLinkORM框架各自爲營的局面。

3.消息驅動bean(message-driven bean)

  它是專門用於異步處理java消息的組件.具有處理大量併發消息的能力.

兩種會話bean

無狀態會話bean

 平常,我們使用最多的是無狀態bean,因爲它的bean實例可供多個用戶使用,所以它的性能比有狀態bean.正因爲一個bean實例被多個用戶使用.那麼,前一個用戶設置的值有可能被後一個用戶所修改,所以它無法正確保存某個用戶設置的值,因此是無狀態的.無狀態bean使用實例池技術管理bean

有狀態會話bean

有狀態bean平常使用的並不多,因爲它的一個bean實例只供一個用戶使用,所以性能開銷比較大,正因爲它的實例只被一個用戶使用,用戶爲它設置的值是不會被其他用戶修改,所以可以正確保存用戶設置的值,因此是有狀態的.狀態bean使用激活(activation)管理bean

            每個用戶都有自己的Bean實例,相當於有多少個用戶就有多少個Bean實例爲之服務。如果不採取任何機制,這樣必然會導致服務器資源嚴重消耗,最後落個down機罷工。爲了解決這個問題,EJB引入了激活機制。該機制實現的原理是這樣的,在EJB服務器需要節省資源時,就從內存中收回bean實例,將其所保持的會話狀態序列化到硬盤中,並且釋放其所佔有的內存。若此時客戶端對EJB再次發起請求,EJB容器會重新實例化一個Bean實例,並從硬盤中將之前的狀態恢復。


客戶端編程

public static void main(String[] args) {

  Properties props = new Properties();

  props.setProperty("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");

  props.setProperty("java.naming.provider.url","localhost:1099");

try {

  InitialContextctx =newInitialContext(props);

  HelloWorldhelloworld = (HelloWorld)ctx.lookup("HelloWorldBean/remote");

  System.out.println(helloworld.sayHello("佛山"));

catch (NamingException e) {

  System.out.println(e.getMessage());

}

}

設置JNDI訪問環境信息

在進行JNDI查找前,我們必須設置應用服務器的上下文信息,主要是設置JNDI驅動的類名(java.naming.factory.initial)和命名服務提供者的URLjava.naming.provider.url) 。

ljava.naming.factory.initialContext.INITIAL_CONTEXT_FACTORY:環境屬性名,用於指定InitialContext工廠(作者稱它爲JNDI驅動更容易理解),它類似於JDBC指定數據庫驅動類。

因爲本例子連接的是JbossNS(命名服務的實現者),所以使用Jboss提供的驅動類:org.jnp.interfaces.NamingContextFactory

ljava.naming.provider.urlContext.PROVIDER_URL:環境屬性名,包含提供命名服務的主機地址和端口號。它類似於JDBC指定數據庫的連接URL。連接到JbossNSURL格式爲:jnp://host:port,該URL的“jnp:”部分是指使用的協議,JBoss使用的是基於Socket/RMI的協議。host爲主機的地址,portJNDI服務的端口。除了host之外,其他部分都是可以不寫的。
l

下面是數據庫訪問例子:

Class.forName("org.gjt.mm.MySQL.Driver").newInstance();

Properties props = new Properties();

props.put("user","root");

props.put("password","123456");

Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/itcast", props);


如同數據庫一樣,根據訪問命名服務器的不同,爲上下文設置的驅動類和URL也是不同的,如下面是訪問Sun應用服務器的上下文信息:

Properties props = new Properties();

props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");

props.setProperty("java.naming.provider.url", "localhost:3700");

InitialContext = newInitialContext(props);

HelloWorldhelloworld = (HelloWorld)ctx.lookup("com.foshanshop.ejb3.HelloWorld");

如果客戶端運行在應用服務器內,我們不需要爲InitialContext設置應用服務器的上下文信息,也不建議設置。因爲應用服務器啓動時會把JNDI驅動類等上下文信息添加進系統屬性,創建InitialContext對象時如果沒有指定Properties參數,InitialContext內部會調用System.getProperty()方法從系統屬性裏獲取必要的上下文信息。對本例子而言,你可以省略傳入props參數,之所以給InitialContext設置參數,目的是引出相關知識點,便於教學。在實際應用中,如果給InitialContext設置了參數,反而會帶來不可移植的問題。

注:創建InitialContext對象時如果沒有指定Properties參數,InitialContext還會在classpath下尋找jndi.properties文件,並從該文件中加載應用服務器的上下文信息。這樣避免了硬編碼爲InitialContext設置Properties參數。

jndi.properties的配置如下:

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory

java.naming.provider.url=localhost:1099

java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

EJB發佈到Jboss時,如果我們沒有爲它指定全局JNDI名稱或修改過其默認EJB名稱,Jboss就會按照默認的命名規則爲EJB生成全局JNDI名稱,默認的命名規則如下:

如果把EJB作爲模塊打包進後綴爲*.earJava EE企業應用文件,默認的全局JNDI名稱是

l本地接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local
l遠程接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remote

      EAR-FILE-BASE-NAMEear文件的名稱,EJB-CLASS-NAMEEJB的非限定類名。

例:把HelloWorld應用作爲EJB模塊打包進名爲HelloWorld.ear的企業應用文件,它的遠程接口的JNDI名稱是:HelloWorld/HelloWorldBean/remote

如果把EJB應用打包成後綴爲*.jar的模塊文件,默認的全局JNDI名稱是

l本地接口:EJB-CLASS-NAME/local
l遠程接口:EJB-CLASS-NAME/remote

例:把HelloWorld應用打包成HelloWorld.jar文件,它的遠程接口的JNDI名稱是:HelloWorldBean/remote

使用註釋改變會話bean的JNDI名

如果我們沒有指定EJBJNDI名稱,當EJB發佈到應用服務器時,應用服務器會按默認規則爲EJB生成全局JNDI名稱。當我們需要自定義JNDI名稱時,可以這樣做

如果EJBJboss中使用,可以使用Jboss提供的@LocalBinding@RemoteBinding註釋,@LocalBinding註釋指定Session BeanLocal接口的JNDI名稱,@RemoteBinding註釋指定Session BeanRemote接口的JNDI名稱,如下:

@Stateless

@Remote ({Operation.class})

@RemoteBinding (jndiBinding="foshanshop/RemoteOperation")

@Local ({LocalOperation.class})

@LocalBinding (jndiBinding="foshanshop/LocalOperation")

public class OperationBean implements Operation,LocalOperation {

}

使用xml部署描述文件改變SessionBeanJNDI名稱

由於JNDI名稱與廠商有關,如果使用註釋定義JNDI名稱會帶來移植問題,因此建議使用ejb-jar.xml部署描述文件進行定義,該文件必須放置在jarMETA-INF目錄下

<?xml version="1.0"encoding="UTF-8"?>

<ejb-jar xmlns=http://java.sun.com/xml/ns/javaee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

                         http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"  version="3.0">

<enterprise-beans>

 <session>

   <ejb-name>HelloWorldBean</ejb-name>

   <mapped-name>HelloWorldBean</mapped-name>

 </session>

</enterprise-beans>

</ejb-jar>

ejb-nameEJB名稱,mapped-namebeanJNDI名稱。目前jboss不支持在ejb-jar.xml通過mapped-name指定JNDI名稱,但我們可以使用他專屬的部署描述文件jboss.xml進行定義,如下:

<?xml version="1.0"encoding="UTF-8" ?>

<!DOCTYPE jboss PUBLIC "-//JBoss//DTDJBOSS 4.2//EN“ "http://www.jboss.org/j2ee/dtd/jboss_4_2.dtd">

<jboss><enterprise-beans> <session>

     <ejb-name>HelloWorldBean</ejb-name>

    <jndi-name>hello/remote</jndi-name>

</session></enterprise-beans></jboss>

本地接口的bean

@Local ({HelloWorldLocal.class})


EJB的調用機制

由於EJB的調用過程對開發者來說是透明的,以至於我們錯誤地認爲:lookup()方法返回的對象就是bean實例。實際上,客戶端與Session bean交互,它並不直接與Bean實例打交道,而是經由bean的遠程或本地接口。當你調用遠程或本地接口的方法時,接口使用的是存根(stub)對象。該存根實現了session bean的遠程或本地接口。它負責將方法調用經過網絡發送到遠程EJB容器,或將請求路由到位於本地JVM內的EJB容器。存根是在部署期間使用JDK所帶的java.lang.reflect.Proxy動態生成。利用RMI、遠程代理實現遠程調用。

第一步:客戶端調用遠程接口的SayHello()方法(實際上調用的是存根對象的SayHello()方法,該存根實現了HelloWorld的遠程接口)。

第二步:方法調用經過IIOPRuntime被轉換成CORBA IIOP消息發往應用服務器。

第三步:應用服務器接收到請求消息後,交由骨架(skeleton)處理。骨架通過IIOP Runtime解析協議消息,並根據協議要求調用bean實例的SayHello()方法。

第四步:骨架(skeleton)將SayHello()方法的返回值經過IIOPRuntime轉換成CORBA IIOP應答消息發回客戶端。

第五步:存根對象通過IIOP RuntimeCORBAIIOP應答消息解析成返回值。


EJB中的依賴注入

注入ejb:

@Stateless

@Remote (Injection.class)

publicclassInjectionBeanimplementsInjection {

       @EJB(beanName="HelloBean")LocalHellohelloworld;

       publicStringSayHello() {

           returnhelloworld.SayHello("注入者");

       }

}

注入數據源:

@Resource(mappedName = "java:/DefaultMySqlDS")DataSourcemyDb;

        Connection conn = null;

        try {

            conn =myDb.getConnection();

            Statementstmt = conn.createStatement();

            ResultSetrs =stmt.executeQuery("SELECTstudentNameFROM student");

            if (rs.next()) str =rs.getString(1); rs.close();

            stmt.close();

        } catch (SQLException e) {

            e.printStackTrace();

        }finally{

            try {

               if(null!=conn && !conn.isClosed())conn.close();

            } catch (SQLException e) {

               e.printStackTrace();

            }

        }
配置數據源

<?xml version="1.0"encoding="UTF-8"?>

<datasources>

  <local-tx-datasource>

    <jndi-name>DefaultMySqlDS</jndi-name>

    <connection-url>jdbc:mysql://localhost:3306/itcast?useUnicode=true&amp;characterEncoding=UTF-8</connection-url>

   <driver-class>org.gjt.mm.mysql.Driver</driver-class>

   <user-name>root</user-name>

   <password>123456</password>

   <min-pool-size>3</min-pool-size>

   <max-pool-size>100</max-pool-size>

  <!--

     TRANSACTION_READ_UNCOMMITTED

     TRANSACTION_READ_COMMITTED

     TRANSACTION_REPEATABLE_READ

     TRANSACTION_SERIALIZABLE

   

   <transaction-isolation>TRANSACTION_SERIALIZABLE</transaction-isolation>-->

  <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>

    <metadata>

      <type-mapping>mySQL</type-mapping>

    </metadata>

  </local-tx-datasource>

</datasources>

實體Bean

它屬於java持久化規範(簡稱JPA)裏的技術,實體bean通過元數據在javabean和數據庫表之間建立起映射關係,然後Java程序員就可以隨心所欲的使用面向對象的編程思想來操縱數據庫。 JPA的出現主要是爲了簡化現有的持久化開發工作和整合ORM技術,目前實現的JPA規範的主流產品有HibernateTopLinkOpenJPAjboss中採用了Hibernate作爲其持久化實現產品

添加JPA的配置文件persistence.xml

根據JPA規範的要求:在實體bean應用中,我們需要在應用的類路徑下的META-INF目錄加入持久化配置文件persistence.xml

<?xml version="1.0"?>

<persistence xmlns="http://java.sun.com/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/persistencehttp://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"version="1.0">

 

</persistence>

 <propertyname="hibernate.hbm2ddl.auto" value="create-drop"/>

<!-- 顯示最終執行的SQL -->

<property name="hibernate.show_sql" value="true"/>

<!-- 格式化顯示的SQL -->

<property name="hibernate.format_sql" value="true"/>


JMS(Java消息服務)

Java 消息服務(Java Message Service,簡稱JMS)是用於訪問企業消息系統的開發商中立的API。企業消息系統可以協助應用軟件通過網絡進行消息交互。

JMS的編程過程很簡單,概括爲:應用程序A發送一條消息到消息服務器的某個目得地(Destination),然後消息服務器把消息轉發給應用程序B。因爲應用程序A和應用程序B沒有直接的代碼關連,所以兩者實現瞭解偶。如下圖:


消息傳遞系統的中心就是消息。一條Message由三個部分組成:

頭(header,屬性(property)和主體(body)。

消息有下面幾種類型,他們都是派生自Message接口。

StreamMessage:一種主體中包含Java基元值流的消息。其填充和讀取均按順序進行。

MapMessage:一種主體中包含一組名-值對的消息。沒有定義條目順序。

TextMessage:一種主體中包含Java字符串的消息(例如,XML消息)。

ObjectMessage:一種主體中包含序列化Java對象的消息。

BytesMessage:一種主體中包含連續字節流的消息。

JMS 支持兩種消息傳遞模型:點對點(point-to-point,簡稱PTP)和發佈/訂閱(publish/subscribe,簡稱pub/sub)。這兩種消息傳遞模型非常相似,但有以下區別:

PTP 消息傳遞模型規定了一條消息只能傳遞給一個接收方。採用javax.jms.Queue表示。

Pub/sub 消息傳遞模型允許一條消息傳遞給多個接收方。採用javax.jms.Topic表示

這兩種模型都通過擴展公用基類來實現。例如:javax.jms.Queuejavax.jms.Topic都擴展自javax.jms.Destination類。

P2P

P/S

配置目標位置

開始JMS編程前,我們需要先配置消息到達的目標地址(Destination),因爲只有目標地址存在了,我們才能發送消息到這個地址。由於每個應用服務器關於目標地址的配置方式都有所不同,下面以jboss爲例,配置一個queue類型的目標地址。

<?xml version="1.0"encoding="UTF-8"?>

<server> 

  <mbean code="org.jboss.mq.server.jmx.Queue"

         name="jboss.mq.destination:service=Queue,name=foshanshop">

    <attributename="JNDIName">queue/foshanshop</attribute>  

    <dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>

  </mbean>

</server>

Jboss使用一個XML文件配置隊列地址,文件的取名格式應遵守*-service.xml

<attribute name="JNDIName">屬性指定了該目標地址的全局JNDI名稱。如果你不指定JNDIName屬性,jboss會爲你生成一個默認的全局JNDI,其名稱由“queue”+“/”+目標地址名稱組成。另外在任何隊列或主題被部署之前,應用服務器必須先部署Destination Manager Mbean,所以我們通過<depends>節點聲明這一依賴。

發送消息

一般發送消息有以下步驟:

(1) 得到一個JNDI初始化上下文(Context)

  InitialContextctx = newInitialContext();

(2) 根據上下文查找一個連接工廠QueueConnectionFactory。該連接工廠是由JMS提供的,不需我們自己創建,每個廠商都爲它綁定了一個全局JNDI,我們通過它的全局JNDI便可獲取它;

  QueueConnectionFactoryfactory = (QueueConnectionFactory)ctx.lookup("QueueConnectionFactory");

(3) 從連接工廠得到一個連接QueueConnection

  conn =factory.createQueueConnection();

(4) 通過連接來建立一個會話(Session);

  session = conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE);

  這句代碼意思是:建立不需要事務的並且能自動確認消息已接收的會話。

(5) 查找目標地址:

  例子對應代碼:Destinationdestination = (Destination )ctx.lookup("queue/foshanshop");

(6) 根據會話以及目標地址來建立消息生產者MessageProducerQueueSenderTopicPublisher都擴展自MessageProducer接口)

例子對應代碼:

MessageProducerproducer =session.createProducer(destination);

TextMessagemsg =session.createTextMessage("您好,這是我的第一個消息驅動Bean");

producer.send(msg);

採用消息驅動Bean接收消息


消息驅動Bean(MDB)是設計用來專門處理基於消息請求的組件。它和無狀態Session Bean一樣也使用了實例池技術,容器可以使用一定數量的bean實例併發處理成百上千個JMS消息。正因爲MDB具有處理大量併發消息的能力,所以非常適合應用在一些消息網關產品。如果一個業務執行的時間很長,而執行結果無需實時向用戶反饋時,也很適合使用MDB。如訂單成功後給用戶發送一封電子郵件或發送一條短信等。

一個MDB通常要實現MessageListener接口,該接口定義了onMessage()方法。Bean通過它來處理收到的JMS消息。

package javax.jms;

public interface MessageListener {

    public void onMessage(Messagemessage);

}

當容器檢測到bean守候的目標地址有消息到達時,容器調用onMessage()方法,將消息作爲參數傳入MDBMDBonMessage()中決定如何處理該消息。你可以使用註釋指定MDB監聽哪一個目標地址(Destination)。當MDB部署時,容器將讀取其中的配置信息。

@MessageDriven(activationConfig =

{

  @ActivationConfigProperty(propertyName="destinationType",

    propertyValue="javax.jms.Queue"),

  @ActivationConfigProperty(propertyName="destination",

    propertyValue="queue/foshanshop"),

  @ActivationConfigProperty(propertyName="acknowledgeMode",

    propertyValue="Auto-acknowledge")

})

public class PrintBean implementsMessageListener {

    public void onMessage(Messagemsg) {

WebService服務

Web服務也是一種分佈式技術,它與EJB最大的不同是,Web服務屬於行業規範,可以跨平臺及語言。而EJB屬於java平臺的規範,儘管理論上可以跨平臺,但實現起來比較複雜,所以其應用範圍侷限在了java平臺。看上去兩者好像是互相競爭的關係,其實不是。它們兩者的偏重點不一樣,Web服務偏重的是這個系統對外提供什麼功能,而EJB偏重的是如何使用一個個組件組裝這些功能。就好比一個硬盤,它對外提供的是存儲服務,這是web服務的關注點,對於怎樣組裝這個硬盤,怎樣構造這些小零件,web服務並不關心,但這些卻是EJB所關注的。

JavaEEweb service提供了兩種不同的編程模型:EJB容器模型及Web容器模型,這裏將以最新的JAX-WS2.x規範(Java API for XML-based Web Services)介紹webservice的開發。

@WebService(targetNamespace="http://ws.foshanshop.com",

  name = "HelloWorld",

  serviceName = "HelloWorldService")

客戶端

開發步驟如下:

1.  在應用的類路徑下放入JAX-WSjar文件(下載路徑https://jax-ws.dev.java.NET)。如果你使用的是JDK6,這一步可以省略,因爲JDK6已經綁定了JAX-WS。目前JDK6綁定的JAX-WS版本是2.0。這意味着,當某些應用使用的JAX-WS版本高於2.0時,就有可能發生版本問題,這時,你需要升級JDK6中的JAX-WS版本,方法如下:

下載最高版本的JAX-WS,在產品lib目錄中找到jaxws-api.jarjaxb-api.jar,把這兩個文件copyJDK6_HOME/jre/lib/endorsed目錄下。

      

  如果有同學使用開發工具是myeclipse這時應該把myeclipse所使用的jdk更改爲你係統安裝的jdk

2.  利用Web Service客戶端生成工具生成輔助類。

3.  第三步:藉助輔助類調用web service


這裏我們使用wsimport工具的Ant任務類生成輔助類

<?xml version="1.0"encoding="UTF-8"?>

<project name="WSClient" default="wsclientgen"basedir=".">

   <propertyname="src.dir" value="${basedir}/src" />

   <path id="build.classpath"description="設置類路徑">

        <fileset dir="${basedir}/lib">

            <includename="*.jar"/>

        </fileset>

    </path>

    <targetname="wsclientgen"description="生成webservice客戶端輔助代碼,執行後請刷新項目">

      <taskdef name="wsimport"classname="com.sun.tools.ws.ant.WsImport"classpathref="build.classpath"/>

      <wsimportwsdl="http://localhost:8080/WsHelloWorld/HelloWorldBean?wsdl"

      sourcedestdir="${src.dir}" package="com.foshanshop.ws.client"keep="true"

      verbose="true" destdir="${basedir}/bin"/>

    </target>

</project>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章