隨筆-3  評(píng)論-1  文章-0  trackbacks-0
            2014年4月9日
          引用:http://leo-faith.iteye.com/blog/177779
          不久前用到了同步,現(xiàn)在回過(guò)頭來(lái)對(duì)JAVA中的同步做個(gè)總結(jié),以對(duì)前段時(shí)間工作的總結(jié)和自我技術(shù)的條理話。JAVA中synchronized關(guān)鍵字能夠作為函數(shù)的修飾符,也可作為函數(shù)內(nèi)的語(yǔ)句,也就是平時(shí)說(shuō)的同步方法和同步語(yǔ)句塊。假如再細(xì)的分類,synchronized可作用于instance變量、object reference(對(duì)象引用)、static函數(shù)和class literals(類名稱字面常量)身上。 
          在進(jìn)一步闡述之前,我們需要明確幾點(diǎn): 
          A.無(wú)論synchronized關(guān)鍵字加在方法上還是對(duì)象上,他取得的鎖都是對(duì)象,而不是把一段代碼或函數(shù)當(dāng)作鎖――而且同步方法很可能還會(huì)被其他線程的對(duì)象訪問(wèn)。 
          B.每個(gè)對(duì)象只有一個(gè)鎖(lock)和之相關(guān)聯(lián)。 
          C.實(shí)現(xiàn)同步是要很大的系統(tǒng)開(kāi)銷作為代價(jià)的,甚至可能造成死鎖,所以盡量避免無(wú)謂的同步控制。 
          接著來(lái)討論synchronized用到不同地方對(duì)代碼產(chǎn)生的影響: 

          假設(shè)P1、P2是同一個(gè)類的不同對(duì)象,這個(gè)類中定義了以下幾種情況的同步塊或同步方法,P1、P2就都能夠調(diào)用他們。 

          1.  把synchronized當(dāng)作函數(shù)修飾符時(shí),示例代碼如下: 
          Public synchronized void method(){ 
          //…. 

          這也就是同步方法,那這時(shí)synchronized鎖定的是哪個(gè)對(duì)象呢?他鎖定的是調(diào)用這個(gè)同步方法對(duì)象。也就是說(shuō),當(dāng)一個(gè)對(duì)象P1在不同的線程中執(zhí)行這個(gè)同步方法時(shí),他們之間會(huì)形成互斥,達(dá)到同步的效果。但是這個(gè)對(duì)象所屬的Class所產(chǎn)生的另一對(duì)象P2卻能夠任意調(diào)用這個(gè)被加了synchronized關(guān)鍵字的方法。 
          上邊的示例代碼等同于如下代碼: 
          public void method() 

          synchronized (this)      //  (1) 

                 //….. 


          (1)處的this指的是什么呢?他指的就是調(diào)用這個(gè)方法的對(duì)象,如P1??梢?jiàn)同步方法實(shí)質(zhì)是將synchronized作用于object reference。――那個(gè)拿到了P1對(duì)象鎖的線程,才能夠調(diào)用P1的同步方法,而對(duì)P2而言,P1這個(gè)鎖和他毫不相干,程式也可能在這種情形下擺脫同步機(jī)制的控制,造成數(shù)據(jù)混亂:( 
          2.同步塊,示例代碼如下: 
          public void method(SomeObject so) { 
          synchronized(so) 

                 //….. 


          這時(shí),鎖就是so這個(gè)對(duì)象,誰(shuí)拿到這個(gè)鎖誰(shuí)就能夠運(yùn)行他所控制的那段代碼。當(dāng)有一個(gè)明確的對(duì)象作為鎖時(shí),就能夠這樣寫(xiě)程式,但當(dāng)沒(méi)有明確的對(duì)象作為鎖,只是想讓一段代碼同步時(shí),能夠創(chuàng)建一個(gè)特別的instance變量(他得是個(gè)對(duì)象)來(lái)充當(dāng)鎖: 
          class Foo implements Runnable 

                 private byte[] lock = new byte[0];  // 特別的instance變量 
              Public void method() 

                 synchronized(lock) { //… } 

          //….. 

          注:零長(zhǎng)度的byte數(shù)組對(duì)象創(chuàng)建起來(lái)將比任何對(duì)象都經(jīng)濟(jì)――查看編譯后的字節(jié)碼:生成零長(zhǎng)度的byte[]對(duì)象只需3條操作碼,而Object lock = new Object()則需要7行操作碼。 
          3.將synchronized作用于static 函數(shù),示例代碼如下: 
                Class Foo 

          public synchronized static void method1()   // 同步的static 函數(shù) 

          //…. 

          public void method2() 

                 synchronized(Foo.class)   //  class literal(類名稱字面常量) 

                 } 
             代碼中的method2()方法是把class literal作為鎖的情況,他和同步的static函數(shù)產(chǎn)生的效果是相同的,取得的鎖很特別,是當(dāng)前調(diào)用這個(gè)方法的對(duì)象所屬的類(Class,而不再是由這個(gè)Class產(chǎn)生的某個(gè)具體對(duì)象了)。 
          記得在《Effective Java》一書(shū)中看到過(guò)將 Foo.class和 P1.getClass()用于作同步鎖還不相同,不能用P1.getClass()來(lái)達(dá)到鎖這個(gè)Class的目的。P1指的是由Foo類產(chǎn)生的對(duì)象。 
          能夠推斷:假如一個(gè)類中定義了一個(gè)synchronized的static函數(shù)A,也定義了一個(gè)synchronized 的instance函數(shù)B,那么這個(gè)類的同一對(duì)象Obj在多線程中分別訪問(wèn)A和B兩個(gè)方法時(shí),不會(huì)構(gòu)成同步,因?yàn)樗麄兊逆i都不相同。A方法的鎖是Obj所屬的那個(gè)Class,而B(niǎo)的鎖是Obj所屬的這個(gè)對(duì)象。 

          小結(jié)如下: 
          搞清楚synchronized鎖定的是哪個(gè)對(duì)象,就能幫助我們?cè)O(shè)計(jì)更安全的多線程程式。 


          更有一些技巧能夠讓我們對(duì)共享資源的同步訪問(wèn)更加安全: 
          1.  定義private 的instance變量+他的 get方法,而不要定義public/protected的instance變量。假如將變量定義為public,對(duì)象在外界能夠繞過(guò)同步方法的控制而直接取得他,并改變他。這也是JavaBean的標(biāo)準(zhǔn)實(shí)現(xiàn)方式之一。 
          2.  假如instance變量是個(gè)對(duì)象,如數(shù)組或ArrayList什么的,那上述方法仍然不安全,因?yàn)楫?dāng)外界對(duì)象通過(guò)get方法拿到這個(gè)instance對(duì)象的引用后,又將其指向另一個(gè)對(duì)象,那么這個(gè)private變量也就變了,豈不是很危險(xiǎn)。 這個(gè)時(shí)候就需要將get方法也加上synchronized同步,并且,只返回這個(gè)private對(duì)象的clone()――這樣,調(diào)用端得到的就是對(duì)象副本的引用了。
          posted @ 2014-04-09 15:27 xzc0202 閱讀(84) | 評(píng)論 (0)編輯 收藏
            2006年10月8日

          摘要:

          XFire是一個(gè)免費(fèi)的開(kāi)源SOAP框架,它不僅可以極大方便地實(shí)現(xiàn)這樣一個(gè)環(huán)境,并且可以提供許多Web Services規(guī)范中高級(jí)特征,這些特征在多數(shù)的商業(yè)或者開(kāi)源工具都沒(méi)有提供。你要恰當(dāng)?shù)睦斫膺@些單詞:great ease and simplicity(非常輕松和簡(jiǎn)單)。你將會(huì)看到使用XFire創(chuàng)建Web Services是多么的簡(jiǎn)單。
          將你的POJO方法發(fā)布為Web Services

          摘要

          問(wèn)一下.Net的開(kāi)發(fā)者,開(kāi)發(fā)Web Services有多困難?他們會(huì)被你的問(wèn)題逗樂(lè),他們會(huì)告訴你所有步驟花費(fèi)的時(shí)間不會(huì)超過(guò)一分鐘。再問(wèn)一下Java開(kāi)發(fā)者,運(yùn)氣好的話你會(huì)碰到上面的回答,一般情況下,你會(huì)得到一個(gè)完全不同的答案。從Web Services引入到Java中至今已經(jīng)5年了,然而它仍然被認(rèn)為是一門(mén)較新的技術(shù),一個(gè)主要的原因就是使用Java實(shí)現(xiàn)Web Services太困難了?,F(xiàn)在,隨著新一代Web Services引擎XFire的發(fā)布,這種情況將會(huì)發(fā)生明顯的變化。使用XFire,你可以把Java類方法發(fā)布為Web Services而不需要編寫(xiě)額外的代碼。在這篇文章中,你將會(huì)看到XFire使Web Services開(kāi)發(fā)變得多么容易和簡(jiǎn)單。

          Web Services使我們能夠在網(wǎng)絡(luò)上建立分布式系統(tǒng),應(yīng)用程序組件可以通過(guò)任何平臺(tái)、任何語(yǔ)言和任何方式訪問(wèn)。無(wú)論應(yīng)用程序如何開(kāi)發(fā),使用了什么語(yǔ)言,以及運(yùn)行在什么操作系統(tǒng)平臺(tái)上,只要它作為Web Service,并且為協(xié)同解決問(wèn)題而設(shè)計(jì),那么你的應(yīng)用程序,以任何語(yǔ)言開(kāi)發(fā)或在任何平臺(tái)上,都可以利用它的服務(wù)。這是Web Service的主要概念。

          為了實(shí)現(xiàn)Web Services的平臺(tái)無(wú)關(guān)性和實(shí)現(xiàn)訪問(wèn)獨(dú)立性,軟件行業(yè)需要遵循一些作為標(biāo)準(zhǔn)的技術(shù)。其中一些包括:
          ---XML:在Web Services環(huán)境中各層之間進(jìn)行傳遞的默認(rèn)數(shù)據(jù)格式。
          ---SOAP:封裝和交換信息的默認(rèn)協(xié)議。第一次被提出時(shí),它是只取Simple Object Access Protocol(簡(jiǎn)單對(duì)象訪問(wèn)協(xié)議)的首字母。但是現(xiàn)在SOAP更多被認(rèn)為是一個(gè)特定的名詞,以它自己而命名,同樣很多人認(rèn)為這是用詞不當(dāng):SOAP實(shí)際上不是用來(lái)訪問(wèn)對(duì)象的。另外,它也不再簡(jiǎn)單。
          ---WSDL(Web Services Description Language,Web Services描述語(yǔ)言):描述Web Services的語(yǔ)言。盡管基于XML并且可以被人理解,WSDL主要是由機(jī)器處理,由客戶端程序讀取和理解。

          下面的高級(jí)層次圖表,基于WWW協(xié)會(huì)發(fā)布的“Web Services Architecture”(Web Services架構(gòu))文檔,顯示了這些技術(shù)在實(shí)際的工作環(huán)境中是如何發(fā)揮作用:

          image
          這個(gè)流程圖顯示了Web Services中的核心技術(shù)是如何工作的。

          這里,Provider是提供服務(wù)的應(yīng)用程序組件,Requester是使用服務(wù)的客戶端程序。很多其他技術(shù)也會(huì)參與到交互中,但是這個(gè)圖只顯示了在Web Services環(huán)境中必需的核心技術(shù)組件。

          XFire是一個(gè)免費(fèi)的開(kāi)源SOAP框架,它不僅可以極大方便地實(shí)現(xiàn)這樣一個(gè)環(huán)境,并且可以提供許多Web Services規(guī)范中高級(jí)特征,這些特征在多數(shù)的商業(yè)或者開(kāi)源工具都沒(méi)有提供。你要恰當(dāng)?shù)睦斫膺@些單詞:great ease and simplicity(非常輕松和簡(jiǎn)單)。你將會(huì)看到使用XFire創(chuàng)建Web Services是多么的簡(jiǎn)單。

          假如你的Web應(yīng)用有一個(gè)Java類,并且你想把它的一個(gè)方法發(fā)布為Web Services,當(dāng)使用XFire時(shí),你不需要編寫(xiě)一行額外的Java代碼。只需要編輯發(fā)布描述符,然后你就會(huì)得到一個(gè)Web Services。是的,它相當(dāng)?shù)睾?jiǎn)單。我們來(lái)看一個(gè)例子。

          版權(quán)聲明:任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必保留以下作者信息和鏈接
          作者:Shahid Ahmed ;mydeman
          原文:http://www.javaworld.com/javaworld/jw-05-2006/jw-0501-xfire.html
          Matrix:http://www.matrix.org.cn/resource/article/2006-09-24/XFire_6bd1061c-4bc6-11db-978f-43b3336b7e51.html
          關(guān)鍵字:XFire;Web Services

          一個(gè)簡(jiǎn)單的Java類

          我們的例子是一個(gè)銀行業(yè)應(yīng)用程序,服務(wù)器是運(yùn)行在J2SE1.4.2_07下的Apache Tomcat5.5.7。假定你已經(jīng)了解如何使用Java編寫(xiě)Web應(yīng)用程序,并知道應(yīng)該如何把它部署到Apache Tomcat服務(wù)器上。我們的Web應(yīng)用程序非常簡(jiǎn)單;它只做一件事——將資金從一個(gè)賬戶轉(zhuǎn)到另外一個(gè)賬戶上。一個(gè)普通的Java類BankingService包含了一個(gè)叫做transferFunds()的方法來(lái)為我們完成這項(xiàng)工作。它需要四個(gè)輸入?yún)?shù):
          1、????????String fromAccount
          2、????????String toAccount
          3、????????double amount
          4、????????String currency

          代碼如下:
          package com.mybank.xfire.example;

          import java.text.NumberFormat;
          import java.text.DecimalFormat;

          /** XFire WebServices sample implementation class.
          */
          public class BankingService implements IBankingService {
          ????
          ????//Default constructor.
          ????public BankingService(){????
          ????}
          ????
          ????/** Transfers fund from one account to another.
          ????*/
          ????public String transferFunds(
          ????????String fromAccount, String toAccount, double amount, String currency){
          ????????
          ????????String statusMessage = "";
          ??????????????????????
          ????????//Call business objects and other components to get the job done.
          ????????//Then create a status message and return.
          ????????try {
          ????????????NumberFormat formatter = new DecimalFormat("###,###,###,###.00");??????
          ????????????statusMessage = "COMPLETED: " + currency + " " + formatter.format(amount)+
          ????????????" was successfully transferred from A/C# " + fromAccount + " to A/C# " + toAccount;
          ????????} catch (Exception e){
          ????????????statusMessage = "BankingService.transferFunds(): EXCEPTION: " + e.toString();
          ????????}
          ????????return statusMessage;
          ????}
          ????
          }


          在這里你看到了什么異常的東西了嗎?或許沒(méi)有,除了默認(rèn)的構(gòu)造函數(shù),類型是public。這是必須的。否則,XFire不能夠初始化這個(gè)類。

          因?yàn)槭褂媒涌诘脑O(shè)計(jì)是一個(gè)好的實(shí)踐,所以我們的Java類也實(shí)現(xiàn)了一個(gè)稱為IBankingService的接口。代碼十分簡(jiǎn)單:
          package com.mybank.xfire.example;

          public interface IBankingService {??

          ????public String transferFunds(
          ????????String fromAccount, String toAccount, double amount, String currency);
          ????????
          }


          在實(shí)際實(shí)現(xiàn)中,這樣一個(gè)方法可能包括各種類型的復(fù)雜調(diào)用、查詢和處理操作。但是我們的示例代碼已經(jīng)最小化了,以至于我們可以集中精力在主要目標(biāo)上:把這個(gè)方法發(fā)布為Web Services。

          你可以看到BankingService是一個(gè)普通的Java類,沒(méi)有任何代碼告訴我們它將會(huì)在Web Services中使用。好的,這里我們不需要增加任何東西。我們所有的工作都在部署描述符里完成。

          Web應(yīng)用的部署描述符

          在Java中,Web應(yīng)用程序通常需要至少一個(gè)部署描述符(叫做web.xml)對(duì)其進(jìn)行配置。XFire本身是一個(gè)基于servlet的應(yīng)用程序。因此,我們需要增加必要的引用到描述符文件中。然后我們還必須配置將要?jiǎng)?chuàng)建的Web Services。我們使用一個(gè)稱為services.xml的新文件來(lái)完成這件事。

          web.xml
          首先,修改web.xml。我們需要增加下面的XFire servlet相關(guān)的條目:
          <servlet>
          ????????<servlet-name>XFireServlet</servlet-name>
          ????????<display-name>XFire Servlet</display-name>
          ????????<servlet-class>org.codehaus.xfire.transport.http.XfireConfigurableServlet
          ???????? </servlet-class>
          ????</servlet>

          ????<servlet-mapping>
          ????????<servlet-name>XFireServlet</servlet-name>
          ????????<url-pattern>/servlet/XFireServlet/*</url-pattern>
          ????</servlet-mapping>
          ????
          ????<servlet-mapping>
          ????????<servlet-name>XFireServlet</servlet-name>
          ????????<url-pattern>/services/*</url-pattern>
          ????</servlet-mapping>


          services.xml
          現(xiàn)在我們不得不說(shuō)一下我們的Web Services的由什么組成的了。這由一個(gè)叫做services.xml的文件完成,它存放在META-INF/xfire目錄下,而這整個(gè)目錄放在WEB-INF/classes文件夾中,它在Web應(yīng)用程序的標(biāo)準(zhǔn)類路徑中。這里是services.xml中的基本配置條目:
          <beans xmlns="http://xfire.codehaus.org/config/1.0">
          ??
          ??<service>
          ????<name>Banking</name>
          ????<namespace>mybank</namespace>
          ????<serviceClass>com.mybank.xfire.example.IBankingService</serviceClass>
          ????<implementationClass>com.mybank.xfire.example.BankingService</implementationClass>
          ??</service>??
          ??
          </beans>


          讓我們看看這里都包含了什么內(nèi)容。Web Services的定義包含在<service>元素中,它還含有一些子元素。第一個(gè)子元素是<name>,它可以是你提供任何的合法名字。這將會(huì)被客戶端程序和其它需要定位你的服務(wù)的組件用到。例如,在服務(wù)準(zhǔn)備好以后,你將在瀏覽器上使用這個(gè)名字來(lái)查看WSDL。

          下一個(gè)子元素是<namespace>。任何合法的XML名字都是可以的。<namespace>用來(lái)唯一標(biāo)識(shí)你的服務(wù)的各個(gè)參數(shù)。
          <serviceClass>元素包含了Java類的名字,它指定了方法簽名。在我們的例子中,它是接口IBankingService。如果Java類沒(méi)有實(shí)現(xiàn)任何接口,你就需要把類的名字放在這里。在你的Java類或者接口中可能有幾個(gè)方法。只需要一個(gè)入口把它們?nèi)堪l(fā)布為Web Services。

          <implementationClass>保存了實(shí)現(xiàn)方法的Java類名。這是一個(gè)可選元素。如果上一個(gè)元素<serviceClass>包含了一個(gè)接口,那么相應(yīng)的實(shí)現(xiàn)類必須在這里指定。

          就是這樣。我們的Web Services配置完成了。

          XFire和其它類庫(kù)

          現(xiàn)在是最后一步了,需要得到所有必需的類庫(kù)。我們?cè)鯓拥玫剿鼈兡??去XFire網(wǎng)站,下載xfire-distribution-1.0.zip,然后解壓到一個(gè)本地文件夾。復(fù)制下面的jar文件和它的庫(kù)文件夾到WEB-INF/lib中:
          ?????????activation-1.0.2.jar
          ?????????commons-codec-1.3.jar
          ?????????commons-httpclient-3.0.jar
          ?????????commons-logging-1.0.4.jar
          ?????????jaxen-1.1-beta-8.jar
          ?????????jdom-1.0.jar
          ?????????log4j-1.2.x.jar
          ?????????mail-1.3.3_01.jar
          ?????????spring-1.2.x.jar
          ?????????stax-api-1.0.jar
          ?????????wsdl4j-1.5.2.jar
          ?????????wstx-asl-2.9.jar
          ?????????xbean-2.1.0.jar
          ?????????xbean-spring-2.2.jar
          ?????????xfire-all-1.0.jar
          ?????????XmlSchema-1.0.jar

          一切妥當(dāng)。我們來(lái)部署和啟動(dòng)應(yīng)用程序。為了部署示例應(yīng)用,只需要復(fù)制websvc.war到Apache Tomcat的webapps文件夾中,再等待幾秒鐘。它將會(huì)自動(dòng)啟動(dòng)。這個(gè)應(yīng)用的全部源代碼也包含在這個(gè)war文件中。我們的程序已經(jīng)準(zhǔn)備作為一個(gè)Web Service了。

          我們?nèi)绾沃繵eb Service正在工作呢?

          為了了解Web Service是否正在工作,我們需要測(cè)試。首先,我們測(cè)試來(lái)看WSDL是否可用。我們?cè)跒g覽器中輸入U(xiǎn)RL。哪個(gè)URL?因?yàn)槲覀兊膽?yīng)用程序的war文件是websvc.war,并且在services.xml中給出的服務(wù)名是Banking,WSDL的URL應(yīng)該是:http://localhost:8080/websvc/services/Banking?wsdl。

          請(qǐng)注意:URL的第一部分,例如,http://localhost:8080,可能會(huì)根據(jù)你的應(yīng)用服務(wù)器不同而不同。無(wú)論怎樣,當(dāng)你輸入U(xiǎn)RL后,將會(huì)看到一個(gè)XML文檔,它的根元素是<wsdl:definitions>。這個(gè)文檔叫做服務(wù)的WSDL。如果你看到了,這就是你的應(yīng)用作為Web Service已經(jīng)可用的第一個(gè)證明。

          但是這個(gè)測(cè)試是不夠的??赡軙?huì)發(fā)生這種情況,可以看到WSDL,但是從客戶端程序可能會(huì)訪問(wèn)不到服務(wù)。因此為了核實(shí)服務(wù)是否可以訪問(wèn)了,我們必須使用一個(gè)客戶端進(jìn)行服務(wù)的實(shí)際調(diào)用來(lái)進(jìn)行一個(gè)真正的測(cè)試。

          開(kāi)發(fā)一個(gè)客戶端

          你可以使用任何的SOAP工具創(chuàng)建客戶端,例如,.Net或者Apache Axis,有很多種方法:使用從WSDL產(chǎn)生的stubs,使用動(dòng)態(tài)代理,等等。在例子中,我們使用一個(gè)動(dòng)態(tài)代理,以一個(gè)簡(jiǎn)單的Servlet形式,叫做WsClient.java。為了保持代碼兩最小,所有在屏幕顯示的元素都放在了doGet()方法中。對(duì)Web Service的實(shí)際調(diào)用由callWebService()方法完成,它相當(dāng)?shù)睾?jiǎn)單。和下面的類似:
          /* Call the Web service
          ????*
          ????*/
          ????public String callWebService(
          ????????String fromAccount, String toAccount, double amount, String currency)
          ????????throws MalformedURLException, Exception {
          ????????
          ????????//Create a metadata of the service??????
          ????????Service serviceModel = new ObjectServiceFactory().create(IBankingService.class);????????
          ????????log.debug("callSoapServiceLocal(): got service model." );
          ??
          ????????//Create a proxy for the deployed service
          ????????XFire xfire = XFireFactory.newInstance().getXFire();
          ????????XFireProxyFactory factory = new XFireProxyFactory(xfire);??????
          ????
          ????????String serviceUrl = "http://localhost:8080/websvc/services/Banking";
          ????????
          ????????IBankingService client = null;
          ????????try {
          ????????????client = (IBankingService) factory.create(serviceModel, serviceUrl);
          ????????} catch (MalformedURLException e) {
          ????????????log.error("WsClient.callWebService(): EXCEPTION: " + e.toString());
          ????????}????
          ??????????????
          ????????//Invoke the service
          ????????String serviceResponse = "";
          ????????try {
          ????????????serviceResponse = client.transferFunds(fromAccount, toAccount, amount, currency);
          ?????? } catch (Exception e){
          ????????????log.error("WsClient.callWebService(): EXCEPTION: " + e.toString());????????????????
          ????????????serviceResponse = e.toString();
          ????????}????????
          ????????log.debug("WsClient.callWebService(): status=" + serviceResponse);??????????????

          ????????//Return the response
          ????????return serviceResponse;
          ????}??


          這個(gè)代碼是如何工作的呢?我來(lái)解釋一下:首先,我們創(chuàng)建一個(gè)服務(wù)模型,它包含服務(wù)的說(shuō)明——換句話說(shuō),就是服務(wù)的元數(shù)據(jù)。我們使用XFire的ObjectServiceFactory從IBankingService.class接口創(chuàng)建這個(gè)模型。

          接著,為XFire獲得一個(gè)代理工廠對(duì)象,它包含了常規(guī)的代碼,也相當(dāng)?shù)睾?jiǎn)單和易懂。這一步中沒(méi)有任何特定應(yīng)用的東西。從這個(gè)proxyFactory,使用服務(wù)模型和服務(wù)端點(diǎn)URL(用來(lái)獲得WSDL),我們可以得到一個(gè)服務(wù)的本地代理。

          就是它了。這個(gè)代理就是實(shí)際的客戶端?,F(xiàn)在,我們可以調(diào)用它的transferFunds()方法來(lái)得到我們需要的Web Service。
          一旦示例應(yīng)用發(fā)布并啟動(dòng),就可以嘗試servlet URL:
          http://localhost:8080/websvc/ws。

          這個(gè)Servlet使用默認(rèn)參數(shù)來(lái)調(diào)用Web Service和顯示接收到的響應(yīng)。頁(yè)面的最后兩行應(yīng)該讀?。?br />Response Received
          COMPLETED: CDN$ 500.00 was successfully transferred from A/C# 11111-01234 to A/C# 99999-05678

          現(xiàn)在你可以確定Web Service已經(jīng)發(fā)布并且在運(yùn)行中了。

          為了嘗試不同的輸入值,你可以使用完整的URL,例如:
          http://localhost:8080/websvc/ws?from=11-2345&to=77-9876&amt=250.00&cur=EUR。

          基本的Web Services開(kāi)發(fā)步驟清單

          這個(gè)清單總結(jié)了將一個(gè)Java方法發(fā)布為Web Service所必須的步驟:
          1、????????檢查Java類的方法和默認(rèn)構(gòu)造函數(shù)確保為public
          2、????????增加X(jué)Fire servlet相關(guān)條目到web.xml中
          3、????????創(chuàng)建services.xml,把它放到WEB-INF/classes/META-INF/xfire目錄下
          4、????????增加X(jué)Fire和第三方包到你的Web應(yīng)用的WEB-INF/lib文件夾中

          這就是所有需要的步驟,是的,相當(dāng)簡(jiǎn)單。

          XFire的其他高級(jí)特性

          XFire的使用可能比較簡(jiǎn)單,但是在特性和功能性上,它卻占據(jù)著領(lǐng)導(dǎo)者的位置。下面是它的高級(jí)特性:
          ---本地?cái)?shù)據(jù)綁定支持POJOs(plain-old Java objects)、XMLBeans、JAXB(Java Architecture for XML Binding)、Castor等等。數(shù)據(jù)綁定說(shuō)明了Web Services的XML請(qǐng)求和映射到Java對(duì)象的XML響應(yīng)。
          ---使用StAX(Streaming API for XML)處理XML文檔。同DOM的基于樹(shù)和SAX的事件驅(qū)動(dòng)的處理方式相比,StAX使用了拉(pull)機(jī)制,它使處理更快速,內(nèi)存效率更高。
          ---支持多種傳輸協(xié)議,如HTTP、JMS(Java Message Service)和JVM內(nèi)部傳輸。
          ---嵌入式,這是XFire的核心功能之一。你可以把這個(gè)SOAP引擎嵌入到你的應(yīng)用中,完全隱藏所有XFire特定引用,同樣所有配置都是程序驅(qū)動(dòng)。
          ---豐富的API,它使XFire可高度自定義,允許開(kāi)發(fā)者在不同的階段截獲請(qǐng)求,并且對(duì)他們進(jìn)行處理。
          ---兼容最新的標(biāo)準(zhǔn)例如SOAP1.1(沒(méi)有加密遠(yuǎn)程工程調(diào)用,或者RPC)和1.2、WSDL1.1、the Web Services Interoperability Organization’s Basic Profile 1.0、Web Services Addressing和WS-Security。

          最重要的是,XFire屬于新一代Web Services引擎。不僅僅是營(yíng)銷用語(yǔ),“新一代”有一些重要的意義。Apache Axis是第一代Java語(yǔ)言的Web Services引擎,已經(jīng)成為了所有后來(lái)工具的參考標(biāo)準(zhǔn)。在過(guò)去的幾年里,Axis以及這些其它的工具已經(jīng)在很多生產(chǎn)環(huán)境中進(jìn)行了實(shí)地測(cè)試。從中得出的一個(gè)關(guān)鍵的問(wèn)題就是Web Services并不最適合RPC類型的通信。對(duì)于性能和效率,面向文檔的消息形式是最好的方式。但是Apache Axis和很多其他的Web Services引擎都被設(shè)計(jì)成了面向RPC的(盡管它們支持文檔形式)。現(xiàn)在,整個(gè)行業(yè)正在開(kāi)發(fā)新一代的SOAP引擎,設(shè)計(jì)為面向文檔的。Apache已經(jīng)宣布結(jié)束舊版本的Axis引擎開(kāi)發(fā),現(xiàn)在專注于Axis2,現(xiàn)在它的預(yù)發(fā)布版本是0.95。XFire在今年的2月份發(fā)布了它的第一個(gè)產(chǎn)品版本(1.0)。它的下一個(gè)版本(1.1)僅僅在幾個(gè)星期之后就進(jìn)行了發(fā)布。

          性能

          Web Services需要消耗很多資源,但是性能方面它們不是那么引人注目。XFire打破了這種趨勢(shì)。它消耗更少的內(nèi)存(部分因?yàn)?StAX的使用),但是表現(xiàn)卻比多數(shù)可比較的SOAP引擎出色。你可以在資源中提供的鏈接中看到比較的結(jié)果。
          此外,XFire還提供了各種方法來(lái)進(jìn)一步優(yōu)化性能。一個(gè)方法是使用JVM內(nèi)置傳輸(in-JVM transport)。如果你知道Web Services和客戶端運(yùn)行在同一個(gè)JVM上,你可以選擇使用本地傳輸,它可以大幅提升性能。在示例中的客戶端代碼,看以下指定服務(wù)端點(diǎn)URL的這行:
          String serviceUrl = "http://localhost:8080/websvc/services/Banking";
          替換為
          String serviceUrl = "xfire.local://Banking";

          你會(huì)看到性能上的明顯提高,因?yàn)樗@過(guò)了整個(gè)網(wǎng)絡(luò)層。

          局限性

          XFire有些重要的局限性你應(yīng)該清楚:
          ---開(kāi)發(fā)Web Services的好的實(shí)踐是從WSDL開(kāi)始。大部分的SOAP引擎提供了從WSDL生成服務(wù)stub的工具。XFire也提供了這樣一個(gè)工具。但是它是基于注釋(annotations-based)的,因此需要J2SE5.0。對(duì)于仍堅(jiān)持使用J2SE1.4.x的人來(lái)說(shuō),它不是一個(gè)令人拍手叫好的工具,因?yàn)槲覀冇泻芏嗥渌绞絹?lái)編寫(xiě)客戶端,一個(gè)就是文章中演示的方式。
          ---附件支持,它將會(huì)包含在未來(lái)發(fā)行的版本中。
          ---易于學(xué)習(xí)的用戶向?qū)?。XFire團(tuán)隊(duì)在這個(gè)方面還有很多工作需要做。

          結(jié)論

          Java當(dāng)前的趨勢(shì)是簡(jiǎn)化技術(shù)的使用。因此,我們正看到一波基于POJO的開(kāi)發(fā)成就。同時(shí),面向服務(wù)架構(gòu)(SOA,Services-oriented architecture)和Web Services已經(jīng)變成了當(dāng)前行業(yè)的熱點(diǎn)話題。XFire正是在這種情況下產(chǎn)生的。它能夠使POJO發(fā)布為最少的Web Services,而只需要付出最小化的努力。從而,它使希望使用這項(xiàng)技術(shù)的初級(jí)開(kāi)發(fā)者的學(xué)習(xí)曲線變得平緩。同時(shí),由于它兼容最新標(biāo)準(zhǔn)和提供了豐富的API,XFire為高級(jí)用戶提供了更多的大好機(jī)會(huì)。

          關(guān)于作者
          Shahid Ahmed是一個(gè)軟件架構(gòu)師,如今在美國(guó)一家主要的無(wú)線運(yùn)行商作咨詢工作。他在22年前開(kāi)始開(kāi)發(fā)軟件,當(dāng)時(shí)Kaypro、Osborne、Apple II和TRS-80s統(tǒng)治著整個(gè)地球。在過(guò)去的7年里,他更多的精力集中于Java。他現(xiàn)在的工作包括SOA、Web Services、消息、POJO、Spring、Ajax等等。Shahid是一個(gè)軟件熱衷者,每天都在奮斗以求在技術(shù)的迷戀和社會(huì)生活的熱愛(ài)之間尋找平衡點(diǎn)。

          資源:
          Matrix Java社區(qū):http://www.matrix.org.cn
          下載本文中的示例應(yīng)用:http://www.javaworld.com/javaworld/jw-05-2006/xfire/jw-0501-xfire.zip
          Web Services架構(gòu):http://www.w3.org/TR/ws-arch/
          WSDL2.0(原來(lái)提議為WSDL1.2,現(xiàn)在重新命名了):第一部分:核心語(yǔ)言(W3C Candidate Recommendation 27 March 2006)
          posted @ 2006-10-08 15:40 xzc0202 閱讀(302) | 評(píng)論 (1)編輯 收藏
          <%@ page contentType="text/html; charset=gb2312" %>
          <%@ page language="java" %>
          <%@ page import="com.mysql.jdbc.Driver" %>
          <%@ page import="java.sql.*" %>

          <%
          ?Connection sqlCon; //數(shù)據(jù)庫(kù)連接對(duì)象

          ?Statement sqlStmt; //SQL語(yǔ)句對(duì)象

          ?ResultSet sqlRst; //結(jié)果集對(duì)象

          ?String strCon; //數(shù)據(jù)庫(kù)連接字符串

          ?String strSQL; //SQL語(yǔ)句

          ?int intPageSize; //一頁(yè)顯示的記錄數(shù)

          ?int intRowCount; //記錄總數(shù)

          ?int intPageCount; //總頁(yè)數(shù)

          ?int intPage; //待顯示頁(yè)碼

          ?String strPage;

          ?int i;

          ?intPageSize = 2; //設(shè)置一頁(yè)顯示的記錄數(shù)

          ?strPage = request.getParameter("page"); //取得待顯示頁(yè)碼

          ?if(strPage==null)
          ?{

          ??//表明在QueryString中沒(méi)有page這一個(gè)參數(shù),此時(shí)顯示第一頁(yè)數(shù)據(jù)

          ??intPage = 1;

          ?}
          ?else
          ?{

          ??//將字符串轉(zhuǎn)換成整型

          ??intPage = java.lang.Integer.parseInt(strPage);

          ??if(intPage<1) intPage = 1;

          ?}

          ?//裝載JDBC驅(qū)動(dòng)程序

          ?? //驅(qū)動(dòng)程序名

          ?? String driverName="com.mysql.jdbc.Driver";

          ?? //數(shù)據(jù)庫(kù)用戶名

          ?? String userName="test";

          ?? //密碼

          ?? String userPasswd="123456";

          ?? //數(shù)據(jù)庫(kù)名
          ?
          ?? String dbName="shujuku";

          ?? //表名

          ?? String tableName="biao";

          ?? //聯(lián)結(jié)字符串

          ?? String url="jdbc:mysql://localhost/"+dbName+"?user="+userName+"&password="+userPasswd;

          ?? Class.forName("com.mysql.jdbc.Driver").newInstance();

          ?? sqlCon=DriverManager.getConnection(url);

          ?? //創(chuàng)建語(yǔ)句對(duì)象
          ?
          ?sqlStmt = sqlCon.createStatement(); //執(zhí)行SQL語(yǔ)句

          ??? strSQL = "select name from " + tableName;

          ??? //執(zhí)行SQL語(yǔ)句并獲取結(jié)果集

          ??? sqlRst = sqlStmt.executeQuery(strSQL);

          ??? //獲取記錄總數(shù)

          ?sqlRst.last();

          ?intRowCount = sqlRst.getRow();

          ?//記算總頁(yè)數(shù)

          ?intPageCount = (intRowCount+intPageSize-1) / intPageSize;

          ?//調(diào)整待顯示的頁(yè)碼

          ?if(intPage>intPageCount) intPage = intPageCount;

          %>

          <html>

          <head>

          <meta http-equiv="Content-Type" content="text/html; charset=gb2312">

          <title>JSP數(shù)據(jù)庫(kù)操作例程 - 數(shù)據(jù)分頁(yè)顯示 - JDBC 2.0 - mysql</title>

          </head>

          <body>

          <table border="1" cellspacing="0" cellpadding="0">

          <tr>

          <th>姓名</th>

          </tr>

          <% if(intPageCount>0)

          {

          ?//將記錄指針定位到待顯示頁(yè)的第一條記錄上

          ?sqlRst.absolute((intPage-1) * intPageSize + 1);

          ?//顯示數(shù)據(jù)

          ?i = 0;

          ?while(i<intPageSize && !sqlRst.isAfterLast()){ %>

          <tr>

          <td>

          <%=sqlRst.getString(1)%>

          </td>

          </tr>

          <% sqlRst.next();

          i++;

          }

          }

          %>

          </table>

          第<%=intPage%>頁(yè) 共<%=intPageCount%>頁(yè)

          <%if(intPage<intPageCount){%><a href="test1.jsp?page=<%=intPage+1%>">下一頁(yè)</a><%}%>

          <%if(intPage>1){%><a href="test1.jsp?page=<%=intPage-1%>">上一頁(yè)</a><%}%>

          </body>

          </html>

          <%

          //關(guān)閉結(jié)果集

          sqlRst.close();

          //關(guān)閉SQL語(yǔ)句對(duì)象

          sqlStmt.close();

          //關(guān)閉數(shù)據(jù)庫(kù)

          sqlCon.close();

          %>
          ?
          ?
          ?

          posted @ 2006-10-08 15:22 xzc0202 閱讀(218) | 評(píng)論 (0)編輯 收藏
          僅列出標(biāo)題  
          主站蜘蛛池模板: 湖南省| 大余县| 林甸县| 水城县| 师宗县| 济南市| 河北区| 襄樊市| 台北县| 沁阳市| 蓬莱市| 白河县| 革吉县| 宜兰县| 环江| 温宿县| 临城县| 吴江市| 报价| 威海市| 巴塘县| 宁津县| 庐江县| 禄劝| 贵州省| 安达市| 张北县| 从江县| 井研县| 高安市| 商都县| 普宁市| 板桥市| 新乡市| 安康市| 斗六市| 霸州市| 保定市| 沾化县| 玉山县| 秭归县|