隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
          數(shù)據(jù)加載中……

          WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理

          本文為原創(chuàng),如需轉(zhuǎn)載,請注明作者和出處,謝謝!

          上一篇:WebService大講堂之Axis2(5):會話(Session)管理

          《WebService大講堂之Axis2(5):會話(Session)管理》一文中介紹了如何使用Axis2來管理同一個服務(wù)的會話,但對于一個復(fù)雜的系統(tǒng),不可能只有一個WebService服務(wù),例如,至少會有一個管理用戶的WebService(用戶登錄和注冊)以及處理業(yè)務(wù)的WebService。象這種情況,就必須在多個WebService服務(wù)之間共享會話狀態(tài),也稱為跨服務(wù)會話(Session)管理。實現(xiàn)跨服務(wù)會話管理與實現(xiàn)同一個服務(wù)的會話管理的步驟類似,但仍然有一些差別,實現(xiàn)跨服務(wù)會話管理的步驟如下:

          實現(xiàn)跨服務(wù)的Session管理需要如下三步:

          1. 使用MessageContextServiceGroupContext獲得與設(shè)置key-value對。

          2. 為要進行Session管理的WebService類所對應(yīng)的<service>元素添加一個scope屬性,并將該屬性值設(shè)為application。

          3. 在客戶端使用setManageSession(true)打開Session管理功能。

          從上面的步驟可以看出,實現(xiàn)跨服務(wù)會話管理與實現(xiàn)同一個服務(wù)的會話管理在前兩步上存在著差異,而第3步是完全一樣的。下面是一個跨服務(wù)的會話管理的實例。在這個例子中有兩個WebService類:LoginServiceSearchService,代碼如下:

          LoginService.java

          package service;
          import org.apache.axis2.context.MessageContext;
          import org.apache.axis2.context.ServiceGroupContext;
          public class LoginService
          {
              
          public boolean login(String username, String password)
              {        
                  
          if("bill".equals(username) && "1234".equals(password))
                  {
                      
          //  第1步:設(shè)置key-value對
                      MessageContext mc = MessageContext.getCurrentMessageContext();
                      ServiceGroupContext sgc 
          = mc.getServiceGroupContext();
                      sgc.setProperty(
          "login""成功登錄");    
                      
          return true;
                  }
                  
          else
                  {
                      
          return false;
                  }
              }    
              
          public String getLoginMsg()
              {
                 
          //  第1步:獲得key-value對中的value
                  MessageContext mc = MessageContext.getCurrentMessageContext();
                  ServiceGroupContext sgc 
          =  mc.getServiceGroupContext();
                  
          return (String)sgc.getProperty("login");    
              }
          }


          SearchService.java

          package service;
          import org.apache.axis2.context.MessageContext;
          import org.apache.axis2.context.ServiceGroupContext;
          public class SearchService
          {
              
          public String findByName(String name)
              {
                  
          //  第1步:獲得key-value對中的value
                  MessageContext mc = MessageContext.getCurrentMessageContext();
                  ServiceGroupContext sgc 
          =  mc.getServiceGroupContext();                
                  
          if (sgc.getProperty("login"!= null)
                      
          return "找到的數(shù)據(jù)<" + name + ">";
                  
          else
                      
          return "用戶未登錄";
              }
          }

          services.xml文件中的配置代碼如下:

          <serviceGroup>
              
          <!--  第2步:添加scope屬性,并設(shè)置屬性值為application -->
              
          <service name="loginService" scope="application">
                  
          <description>
                      登錄服務(wù)
                  
          </description>
                  
          <parameter name="ServiceClass">
                      service.LoginService
                  
          </parameter>
                  
          <messageReceivers>
                      
          <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
                          class
          ="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
                  
          </messageReceivers>
              
          </service>
              
          <!--  第2步:添加scope屬性,并設(shè)置屬性值為application -->
              
          <service name="searchService" scope="application">
                  
          <description>
                      搜索服務(wù)
                  
          </description>
                  
          <parameter name="ServiceClass">
                      service.SearchService
                  
          </parameter>
                  
          <messageReceivers>
                      
          <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
                          class
          ="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
                  
          </messageReceivers>
              
          </service>
          </serviceGroup>


          3步與《WebService大講堂之Axis2(5):會話(Session)管理》一文中介紹的方法類似。

          下面是使用兩個stub類的對象實例訪問上面實現(xiàn)的兩個WebService的客戶端代碼:

          LoginServiceStub stub = new LoginServiceStub();
          LoginServiceStub.Login login 
          = new LoginServiceStub.Login();
          login.setUsername(
          "bill");
          login.setPassword(
          "1234");
          if(stub.login(login).local_return)
          {
              System.out.println(stub.getLoginMsg().local_return);
              SearchServiceStub searchStub 
          = new SearchServiceStub();
              SearchServiceStub.FindByName fbn 
          = new SearchServiceStub.FindByName();
              fbn.setName(
          "abc");
              System.out.println(searchStub.findByName(fbn).local_return); 
          }

          在執(zhí)行上面的代碼后,將輸出如下的信息:

          成功登錄

          找到的數(shù)據(jù)
          <abc>

          讀者可以將scope屬性值改成transportsession,看看會輸出什么!

              實際上,Axis2的會話管理也是通過Cookie實現(xiàn)的,與Web應(yīng)用中的Session管理類似。如果讀者使用C#訪問支持會話(在同一個服務(wù)中的會話管理)的WebService,需要指定一個CookieContainer對象,代碼如下:

          service.loginService ls = new service.loginService();
          System.Net.CookieContainer cc 
          = new System.Net.CookieContainer();
          ls.CookieContainer 
          = cc;
          bool r, rs;
          ls.login(
          "bill""1234"out @r, out rs);
          if (r)
          {
              MessageBox.Show(ls.getLoginMsg().@return);
          }

          如果是訪問跨服務(wù)的支持會話的WebService,則不需要指定CookieContainer對象,代碼如下:

          service.loginService ls = new service.loginService();
          bool r, rs;
          ls.login(
          "bill""1234"out @r, out rs);
          if (r)
          {
              service1.searchService ss 
          = new service1.searchService();
              MessageBox.Show(ss.findByName(
          "abc"));
          }

          如果讀者使用delphi(本文使用的是delphi2009,其他的delphi版本請讀者自行測試)調(diào)用支持會話的WebService時有一些差別。經(jīng)筆者測試,使用delphi調(diào)用WebService,將scope屬性值設(shè)為transportsessionapplication都可以實現(xiàn)跨服務(wù)的會話管理,這一點和JavaC#不同,JavaC#必須將scope屬性值設(shè)為application才支持跨服務(wù)會話管理。在delphi中不需要象C#指定一個CookieContainer或其他類似的對象,而只需要象訪問普通的WebService一樣訪問支持會話的WebService即可。

          下一篇:
          WebService大講堂之Axis2(7):將Spring的裝配JavaBean發(fā)布成WebService





          Android開發(fā)完全講義(第2版)(本書版權(quán)已輸出到臺灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2009-02-03 23:42 銀河使者 閱讀(13845) 評論(20)  編輯  收藏 所屬分類: java 原創(chuàng) 、webservice

          評論

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          謝謝你的文章,很有用阿
          2009-02-05 13:38 | IT公司面試手冊

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          大哥,牛人啊~~贊
          2009-02-05 23:33 | zuzong

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          文章很有用,想問一個問題,
          怎樣實現(xiàn)超時自動終止會話呢?
          2009-02-07 13:31 | yapituy

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          我每次使用相同的客戶端訪問,以前會話的內(nèi)容還都存在,怎樣才能使長時間不用的會話自動斷開
          2009-02-07 13:34 | yapituy

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          這是application級別的,只有服務(wù)器重啟或重新發(fā)布應(yīng)用程序會話才會消失。而其他級別的我試了一下,并不能跨服務(wù)共享會話。
          2009-02-07 17:18 | 銀河使者

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          有個項目,我準(zhǔn)備使用application級別的會話管理,但客戶端比較多,如果保存那么多的會話而不斷開的話,會不會對服務(wù)器造成很大的壓力?又沒什么比較好的解決方法實現(xiàn)會話的超時斷開的功能?謝謝!
          2009-02-07 21:16 | yapituy

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          不知你的用戶有多少,10000,還是20000,或更多,一個會話只占很小的內(nèi)存。當(dāng)然,除了使用會話解決你的問題外,還有另外一個方法可以達到同樣的效果。使用會話的目的是為了進行權(quán)限驗證,你可以為每一個web service方法都加上一個用戶名和密碼,可以將這些放到類中進行傳遞,這樣就不需要會話了,每次調(diào)用方法程序都從數(shù)據(jù)庫中驗證,你也可以定義一個靜態(tài)的Map對象在服務(wù)端來保存經(jīng)常登錄的用戶名和密碼,這樣當(dāng)這些用戶調(diào)用該方法時就不用再到數(shù)據(jù)庫中去驗證了。如博客園和blogjava所使用的msn writer寫blog,就是使用的MetaWebBlog API,這個API雖然不是Web Service(只是一個遠程方法調(diào)用),但使用的就是我說的第二種方法,每一方法都有一個用戶名和密碼。你看看這些方法就知道了:http://www.cnblogs.com/nokiaguy/services/metaweblog.aspx
          2009-02-07 21:34 | 銀河使者

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          另外會話是可以持久化的,但不知axis2是如何處理的
          2009-02-07 21:35 | 銀河使者

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          能否在登錄的時候在會話中記錄登錄時間,然后每次調(diào)用方法前,取當(dāng)前時間進行判斷,如果時間間隔大于你的設(shè)定值,無法繼續(xù)操作,需要重新登錄?
          2009-02-09 16:44 | jiangminjie

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          @jiangminjie
          也可以,這種方法
          2009-02-09 16:51 | 銀河使者

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          呵呵,修改了一下ConfigurationContext類,在處理application會話時,增加了一個處理超時的方法。
          2009-02-10 11:06 | yapituy

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          還得請教問題,關(guān)于handler中拋出AxisFault異常的。
          在handler(使用java)中判斷用戶是否登陸,如果未登錄拋出一個AxisFault異常??蛻舳耍ㄊ褂胏#)無法捕獲此異常,捕捉到的異常是InvalidOperationException,但如果在service中拋出AxisFault,客戶端可以捕獲SoapException。怎樣處理客戶端才能捕獲到handler中的SoapException?謝謝 !
          2009-02-10 11:27 | yapituy

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          @yapituy
          這個我也試了,但客戶端也是未補獲AxisFault異常,我用java、c#和delphi試的客戶端,都未補獲AxisFault異常,不知axis2內(nèi)部是如何處理的,也許是有bug,也許是服務(wù)端程序的設(shè)置問題,最終還沒解決,還是就是超時的問題,可能是axis2本身的問題。
          2009-02-10 11:46 | 銀河使者

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          我問題中說的可能有點亂,在服務(wù)端拋出AxisFault,c#客戶端捕捉到SoapException異常應(yīng)該是正確的。上午說的問題應(yīng)該是handler配置的有問題,只配InFlow就可以捕捉到SoapException了,而我把OutFlow、InFaultFlow、OutFaultFlow也都給配置上了。
          2009-02-10 14:36 | yapituy

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          這路有一個問題,如果我的用戶名密碼是存在數(shù)據(jù)庫里面的,一旦我對一個用戶修改密碼或者干脆就刪除掉這個用戶,那么這樣就必須重啟服務(wù)器才能在驗證這部分生效;所以目前這個實現(xiàn)辦法還是不能夠接受的,必須能夠讓session內(nèi)的東西自動超時才行。
          既然scope 為應(yīng)用級別的,可以想辦法用另外一個線程去維護用戶信息的超時狀態(tài)
          2009-02-17 12:10 | Alexwan

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          @Alexwan
          如果用戶修改密碼,可以在修改密碼后將session里的相關(guān)內(nèi)容刪除,這樣客戶端必須要重新登錄才能繼續(xù)使用了。
          2009-02-17 12:19 | 銀河使者

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理[未登錄]  回復(fù)  更多評論   

          @銀河使者
          我也想問問怎么把session里的相關(guān)內(nèi)容刪除?
          最好能徹底將這個session刪除。
          2009-09-04 15:41 | todd

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          我用Java實現(xiàn)的,沒想到將scope設(shè)置成transportsession和application都能夠跨服務(wù)訪問,暈死了,還有,我沒有實現(xiàn)博主說的第三步,實驗了N次了,哎,不曉得這個原理到底是怎么回事了
          2010-01-05 12:05 | Mr.Blue

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          樓主你好 我在scope中設(shè)置了application但是訪問結(jié)果還是跟設(shè)置了transportsession一樣 不能跨服務(wù)會話 請問這是為什么
          <serviceGroup>

          <service name="ManageSession" scope="application">
          <description>
          This is my first webservice which use session.
          </description>
          <parameter name="ServiceClass">com.sha0k.webservice.session.LoginService</parameter>
          <operation name="login">
          <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
          </operation>
          <operation name="getLoginMsg">
          <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
          </operation>
          </service>

          <service name="SearchSession" scope="application">
          <description>
          This is my first webservice which use application session.
          </description>
          <parameter name="ServiceClass">com.sha0k.webservice.session.SearchService</parameter>
          <operation name="findByName">
          <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
          </operation>
          </service>

          </serviceGroup>
          2011-11-21 23:45 | sha0kun

          # re: WebService大講堂之Axis2(6):跨服務(wù)會話(Session)管理  回復(fù)  更多評論   

          我的客戶端 session管理 是開啟的 RPCServiceClient serviceClient = new RPCServiceClient();
          Options options = serviceClient.getOptions();
          options.setManageSession(true);
          2011-11-21 23:46 | sha0kun
          主站蜘蛛池模板: 邯郸县| 关岭| 周至县| 巴中市| 安吉县| 正镶白旗| 中山市| 乾安县| 神农架林区| 乳山市| 麻江县| 察隅县| 青龙| 台中市| 东安县| 太仓市| 鄂伦春自治旗| 石家庄市| 武宁县| 视频| 女性| 鲁山县| 明光市| 中超| 龙州县| 明水县| 江城| 揭西县| 张家川| 新邵县| 赤峰市| 晋城| 德州市| 沙田区| 诸暨市| 石首市| 潮安县| 阳江市| 修文县| 屯门区| 左贡县|