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

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

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

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

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

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

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

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

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

          從上面的步驟可以看出,實(shí)現(xiàn)跨服務(wù)會(huì)話管理與實(shí)現(xiàn)同一個(gè)服務(wù)的會(huì)話管理在前兩步上存在著差異,而第3步是完全一樣的。下面是一個(gè)跨服務(wù)的會(huì)話管理的實(shí)例。在這個(gè)例子中有兩個(gè)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對(duì)
                      MessageContext mc = MessageContext.getCurrentMessageContext();
                      ServiceGroupContext sgc 
          = mc.getServiceGroupContext();
                      sgc.setProperty(
          "login""成功登錄");    
                      
          return true;
                  }
                  
          else
                  {
                      
          return false;
                  }
              }    
              
          public String getLoginMsg()
              {
                 
          //  第1步:獲得key-value對(duì)中的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對(duì)中的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):會(huì)話(Session)管理》一文中介紹的方法類似。

          下面是使用兩個(gè)stub類的對(duì)象實(shí)例訪問(wèn)上面實(shí)現(xiàn)的兩個(gè)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,看看會(huì)輸出什么!

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

          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èn)跨服務(wù)的支持會(huì)話的WebService,則不需要指定CookieContainer對(duì)象,代碼如下:

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

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





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

          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) 評(píng)論(20)  編輯  收藏 所屬分類: java 、 原創(chuàng) 、webservice

          評(píng)論

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

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

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

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

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

          文章很有用,想問(wèn)一個(gè)問(wèn)題,
          怎樣實(shí)現(xiàn)超時(shí)自動(dòng)終止會(huì)話呢?
          2009-02-07 13:31 | yapituy

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

          樓主你好 我在scope中設(shè)置了application但是訪問(wèn)結(jié)果還是跟設(shè)置了transportsession一樣 不能跨服務(wù)會(huì)話 請(qǐng)問(wèn)這是為什么
          <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ù)會(huì)話(Session)管理  回復(fù)  更多評(píng)論   

          我的客戶端 session管理 是開(kāi)啟的 RPCServiceClient serviceClient = new RPCServiceClient();
          Options options = serviceClient.getOptions();
          options.setManageSession(true);
          2011-11-21 23:46 | sha0kun
          主站蜘蛛池模板: 武威市| 徐汇区| 兴义市| 穆棱市| 满城县| 大悟县| 玛纳斯县| 诸城市| 彰化县| 蛟河市| 渑池县| 衡南县| 梅州市| 合川市| 磴口县| 调兵山市| 嘉善县| 安新县| 宁陕县| 泸水县| 崇仁县| 沙雅县| 中江县| 温州市| 右玉县| 贺州市| 浮梁县| 北辰区| 宜阳县| 永寿县| 新沂市| 衡东县| 星座| 靖西县| 达孜县| 吴忠市| 开原市| 连州市| 上思县| 阆中市| 沂南县|