我的漫漫程序之旅

          專注于JavaWeb開發(fā)
          隨筆 - 39, 文章 - 310, 評論 - 411, 引用 - 0
          數(shù)據(jù)加載中……

          XFire客戶端流程分析

          XFire是當前J2EE領域非常流行的Web Service框架,以其卓越的性能和簡單易用的特性博得了廣大開發(fā)者的青睞。目前XFire已經(jīng)演變?yōu)?/span>ApacheCXF項目,但仍有大量用戶在使用XFire。

          下面是XFire客戶端調(diào)用的流程分析圖,本文后續(xù)本分將圍繞該圖展開。

          XFire客戶端的調(diào)用非常靈活,可以有很多種方式,如通過配置調(diào)用、通過API編程調(diào)用或者與SpringIoC框架集成使用。雖然調(diào)用方式靈活多樣,但萬變不離其中,其內(nèi)部流程是一致的。

          創(chuàng)建服務模型

          服務模型是XFire中非常重要的概念之一,包含了服務的接口信息、操作信息、Binding信息等諸多服務調(diào)用過程中需要的信息。因此在進行服務調(diào)用之前首先要創(chuàng)建服務模型。創(chuàng)建服務模型的工作是由服務工廠ServiceFactory完成的,用戶需要為服務工程提供服務接口、名稱、命名空間等一些信息,其中服務接口是必須的,其他為可選信息。

          創(chuàng)建Client實例

          ClientXFire客戶端的核心組成部分,間接的代表了一個服務。當為具體某個服務配置攔截器(Handler,有很多種譯法如攔截器、處理器、過濾器等,本文統(tǒng)一用攔截器)時,其實是將攔截器信息應用到Client實例上。Client可以手工創(chuàng)建也可以由XFireProxyFactory創(chuàng)建,無論通過哪種方式,Client在初始化過程中最重要的一步都是在out攔截器堆棧中增加一個OutMessageSender攔截器。該攔截器負責最終將服務調(diào)用通過HTTP發(fā)送到服務提供者并返回處理結果。本文后續(xù)部分還會對OutMessageSender做更加詳細的講解。

          創(chuàng)建服務代理對象

          XFireProxy,XFire SOAP客戶端代理實現(xiàn),用戶調(diào)用服務時(如Hello.echo(“tony”))就是通過該對象的invoke方法來執(zhí)行。實際上,XFireProxy只是將調(diào)用代理到Client實例,最終執(zhí)行服務的還是Client實例。

          構造調(diào)用鏈信息

          Client實例的invoke方法在執(zhí)行時,生成了一個Invocation對象,該對象構造了一次完整的調(diào)用信息,包括OutMessage、MessageContext等。同時Invocation還負責構造一個攔截器管道(HandlerPipeline),該管道包含了本次調(diào)用需要執(zhí)行的所有攔截器,當然也包括OutMessageSender。這些攔截器會分不同的階段來執(zhí)行,這也是XFire一個特性。XFire默認定義了很多階段(Phase),每個階段都會有若干攔截器被調(diào)用。

          循環(huán)調(diào)用攔截器

          攔截器(Handler)是XFire中最為重要的概念,一次服務調(diào)用就是由若干攔截器組合完成的。XFire默認提供了很多預定義的攔截器,用戶也可以定義自己的攔截器。基本上,通過攔截器可以影響XFire執(zhí)行過程中的任何步驟,你可以為所欲為:)

          攔截器有兩個重要的概念,一個是階段(Phase),一個是順序(Order)。這兩個因素共同決定了攔截器的執(zhí)行順序??梢栽谌齻€不同的地方配置攔截器:

          n         XFire實例:全局攔截器,對所有通道上的所有服務起作用

          n         Transport:通道特定的攔截器,只對該通道(如HTTP、JMS)起作用

          n         具體服務:服務特定的攔截器,只對該服務起作用

          其實,具體服務上的攔截器最終是配置到Client上。對于同一個階段上的攔截器,執(zhí)行順序為“具體服務—>Transport>XFire實例”。千萬不要忽視這些順序,這對你正確的使用攔截器非常有幫助。

          發(fā)送遠程服務請求

          這是整個調(diào)用鏈中最后的一環(huán),也是最關鍵的一步。OutMessageHandler,前文已經(jīng)有所提及,是一個特殊的攔截器,在Client初始化時創(chuàng)建并加入調(diào)用鏈中。該攔截器處于攔截器調(diào)用鏈的Phase.SEND階段,基本上也是最后的階段。OutMessageHandler從當前調(diào)用的消息上下文(MessageContext)中獲取請求的服務地址URI以及SOAP消息,然后通過HTTPSOAP請求發(fā)送到遠程服務器(針對HTTP通道,如果是JMS通道則發(fā)送到指定的目的地)。最終將遠程服務器的響應逐級返回給調(diào)用者。

          案例分析

          前文很多地方都提到Handler非常重要,那么具體有那些應用場景呢?本部分通過兩個案例逐步演示Handler的應用。

          一、             簡單安全驗證

          這是一個非常典型的應用場景,假設A公司對外提供了一個旅程信息查詢服務,該服務通過XFire對外發(fā)布。但是A公司只希望其合作伙伴才能使用該服務,那么A公司可以為該服務配置一個Handler,該HandlerSOAP的消息頭中獲取認證字符串,只有通過驗證的請求才被執(zhí)行。下面是簡單的示例代碼,真實情況要比這復雜得多。

          publicvoid invoke(MessageContext context) throws Exception {

          Element header = context.getInMessage().getHeader();  

               String authCode = header.getChild("authCode",null).getValue();

               if(!"tony".equals(authCode)){

                  thrownew XFireFault("Authentication Fail!", XFireFault.SENDER);

            }

          }

          對于A公司的合作伙伴,要想調(diào)用該服務,必須在其SOAP的消息頭中包含上面代碼中的驗證字符串,否則服務將被拒絕。下面是簡單的示例代碼:

              publicvoid invoke(MessageContext context) throws Exception {

                  Element header = context.getInMessage().getHeader();

                  Element authCode = new Element("authCode");

                  authCode.addContent("tony");

                  header.addContent(authCode);

              }

          二、             查找真實服務

          這是一個比較特殊的應用場景:假設A公司已經(jīng)初步實現(xiàn)SOA,擁有一個服務注冊中心,所有的XFire服務都在該中心注冊??蛻舳嗽谡{(diào)用服務時需要動態(tài)的從該服務注冊中心獲取當前的服務地址及版本。通過其他方式肯定也可以實現(xiàn)該需求,但是通過Handler來實現(xiàn)會非常的幽雅,而且對應用不需要做任何變動。我們先來看一下Handler的代碼:

              publicvoid invoke(MessageContext context) throws Exception {

                      // 1.尋址

                      lookupRealServiceUri(context);

          }

              privatevoid lookupRealServiceUri(MessageContext context) {

                  String uri = context.getOutMessage().getUri();

                  try {

                      uri = serviceLocator.lookup(requestEnvironment, uri);

                  } catch (Exception e) {

                      // Ignoral this exception

                  }

                  context.getOutMessage().setUri(uri);

              }

          正如代碼所示,只需要從context中獲取當前請求的服務URI地址,然后用當前請求環(huán)境信息及服務URI地址到服務注冊中心查找真實的服務,并重新設置服務的地址。

          結束語

          本文粗略的介紹了XFire客戶端的調(diào)用流程,并著重講解了Handler的擴展機制及其應用場景,力求讀者能夠通過本文對XFire能有更加深入的了解和掌握。文中難免存在不足之處,歡迎任何形式的交流。



          posted on 2008-05-07 11:09 々上善若水々 閱讀(2645) 評論(2)  編輯  收藏 所屬分類: WebService

          評論

          # re: XFire客戶端流程分析  回復  更多評論   

          嘿嘿,看了這一篇對XFire客戶端有了大概的了解了,謝謝
          2008-05-09 13:58 | racnow

          # re: XFire客戶端流程分析  回復  更多評論   

          我是一名新手看了你寫的文章對我?guī)椭艽?!謝了!
          2009-07-17 12:38 | 黯鄉(xiāng)魂
          主站蜘蛛池模板: 博白县| 读书| 凤阳县| 华阴市| 阿克陶县| 宜良县| 湘阴县| 靖江市| 张家界市| 漠河县| 永川市| 大城县| 通山县| 广平县| 德昌县| 临洮县| 松阳县| 霍邱县| 固始县| 西华县| 岳阳市| 龙口市| 抚州市| 黎川县| 霍山县| 互助| 潼关县| 阳信县| 吉水县| 突泉县| 射洪县| 梧州市| 绍兴县| 美姑县| 朔州市| 台山市| 麻阳| 石台县| 安龙县| 湟中县| 漠河县|