Enterprice JavaBeans是一個用於分佈式業務應用的標準服務端組件模型。採用Enterprice JavaBeans架構編寫的應用是可伸縮的、事務性的、多用戶安全的。
採用ejb編寫的這些應用,可以部署在任何支持Enterprice JavaBeans規範的服務器平臺,如jboss、weblogic等。
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_16。Jdk安裝完後,接着問你是否安裝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容器。
是一個成熟的開源的準JavaEE應用服務器,在開源JavaEE應用服務器中所佔市場份額第一。如果你打算選用開源的JavaEE應用服務器,那麼jboss是最值得選擇的。
是一個開源的JavaEE應用服務器,對JavaEE規範的支持非常好,其運行性能比較高。因爲發展時間相對較短,市場佔有率比較低。另外,它能否提供穩定的運行性能,還有待時間的考驗。
是商業市場佔有率第一的商業JavaEE應用服務器,它具有出色的穩定性,並提供了人性化的管理界面,還有企業需要使用到的衆多功能。
商業JavaEE應用服務器,如果你打算選用商業應用服務器運行ejb3,這個是不錯的選擇。
商業JavaEE應用服務器,如果你的數據庫是Oracle,要想兼容性更好,這個是不錯的選擇。
這是國內的商業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”。
進入jboss的bin目錄,找到啓動腳本run.bat。雙擊run.bat即可啓動jboss,此時啓動的配置項爲default。
如果啓動出錯,請檢查下列情況:
1.端口是否被佔用,如:8080、1099
2是否爲JDK設置的JAVA_HOME和ClassPath系統變量,如果沒有,請按照前面視頻介紹的方法設置。
3.檢查jboss所用的jdk是否1.5以上版本,這些信息可以在jboss的控制檯觀察到。
4.如果啓動時出現這樣的錯誤:“findstr不是內部或外部命令,也不是可運行的程序或批處理文件”。那麼應該在系統變量Path中追加“%SystemRoot%\system32;%SystemRoot%;”。
最後的辦法是重裝機器上的JDK,祝你好運。
可以在jboss安裝路徑的client目錄下找到,通常會把client目錄下的所有jar文件添加到項目的類路徑下.
EJB中的三種bean
1.會話bean(session bean)
負責與客戶端交互,是編寫業務邏輯的地方,在會話bean中可以通過jdbc直接操作數據庫,但大多數情況下都是通過實體bean來完成對數據庫的操作.
2.實體bean(entity bean)
它實際上屬於java持久化規範(簡稱JPA)裏的技術,JPA的出現主要是爲了簡化現有的持久化開發工作和整合ORM技術,結束現在hibernate、TopLink等ORM框架各自爲營的局面。
3.消息驅動bean(message-driven bean)
它是專門用於異步處理java消息的組件.具有處理大量併發消息的能力.
兩種會話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)和命名服務提供者的URL(java.naming.provider.url) 。
因爲本例子連接的是JbossNS(命名服務的實現者),所以使用Jboss提供的驅動類:org.jnp.interfaces.NamingContextFactory
下面是數據庫訪問例子:
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作爲模塊打包進後綴爲*.ear的Java EE企業應用文件,默認的全局JNDI名稱是
EAR-FILE-BASE-NAME爲ear文件的名稱,EJB-CLASS-NAME爲EJB的非限定類名。
例:把HelloWorld應用作爲EJB模塊打包進名爲HelloWorld.ear的企業應用文件,它的遠程接口的JNDI名稱是:HelloWorld/HelloWorldBean/remote
如果把EJB應用打包成後綴爲*.jar的模塊文件,默認的全局JNDI名稱是
例:把HelloWorld應用打包成HelloWorld.jar文件,它的遠程接口的JNDI名稱是:HelloWorldBean/remote
使用註釋改變會話bean的JNDI名
如果我們沒有指定EJB的JNDI名稱,當EJB發佈到應用服務器時,應用服務器會按默認規則爲EJB生成全局JNDI名稱。當我們需要自定義JNDI名稱時,可以這樣做
如果EJB在Jboss中使用,可以使用Jboss提供的@LocalBinding和@RemoteBinding註釋,@LocalBinding註釋指定Session Bean的Local接口的JNDI名稱,@RemoteBinding註釋指定Session Bean的Remote接口的JNDI名稱,如下:
@Stateless
@Remote ({Operation.class})
@RemoteBinding (jndiBinding="foshanshop/RemoteOperation")
@Local ({LocalOperation.class})
@LocalBinding (jndiBinding="foshanshop/LocalOperation")
public class OperationBean implements Operation,LocalOperation {
}
使用xml部署描述文件改變SessionBean的JNDI名稱
由於JNDI名稱與廠商有關,如果使用註釋定義JNDI名稱會帶來移植問題,因此建議使用ejb-jar.xml部署描述文件進行定義,該文件必須放置在jar的META-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-name爲EJB名稱,mapped-name爲bean的JNDI名稱。目前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 Runtime將CORBAIIOP應答消息解析成返回值。
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&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規範的主流產品有Hibernate、TopLink和OpenJPA,在jboss中採用了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.Queue和javax.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) 根據會話以及目標地址來建立消息生產者MessageProducer(QueueSender和TopicPublisher都擴展自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()方法,將消息作爲參數傳入MDB。MDB在onMessage()中決定如何處理該消息。你可以使用註釋指定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所關注的。
JavaEE爲web 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-WS的jar文件(下載路徑: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.jar和jaxb-api.jar,把這兩個文件copy到JDK6_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>