axis2開發webservice之跨服務會話(Session)管理

axis2開發webservice之跨服務會話(Session)管理

分類: Web Service

         之前學習了同一服務中的session管理點擊打開鏈接,今天來看一下跨服務的session管理,本來昨天晚上把服務器端都寫好了,只剩下客戶端的代碼了,無奈,下班了,只好今天早上接着寫了,也好就當是複習了。

        對於一個複雜的系統,不可能只有一個WebService服務,例如,至少會有一個管理用戶的WebService(用戶登錄和註冊)以及處理業務的WebService。象這種情況,就必須在多個WebService服務之間共享會話狀態,也稱爲跨服務會話(Session)管理。實現跨服務會話管理與實現同一個服務的會話管理的步驟類似,但仍然有一些差別,實現跨服務會話管理的步驟如下:

實現跨服務的Session管理需要如下三步:

1. 使用MessageContextServiceGroupContext獲得與設置key-value對。

2. 爲要進行Session管理的WebService類所對應的<service>元素添加一個scope屬性,並將該屬性值設爲application

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

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

[java] view plaincopy
  1. package crossSession;  
  2.   
  3. import org.apache.axis2.context.MessageContext;  
  4. import org.apache.axis2.context.ServiceGroupContext;  
  5. public class LoginService  
  6. {  
  7.     public boolean login(String username, String password)  
  8.     {          
  9.         if("bill".equals(username) && "1234".equals(password))  
  10.         {  
  11.             //  第1步:設置key-value對  
  12.             MessageContext mc = MessageContext.getCurrentMessageContext();  
  13.             ServiceGroupContext sgc = mc.getServiceGroupContext();  
  14.             sgc.setProperty("login""成功登錄");      
  15.             return true;  
  16.         }  
  17.         else  
  18.         {  
  19.             return false;  
  20.         }  
  21.     }      
  22.     public String getLoginMsg()  
  23.     {  
  24.        //  第1步:獲得key-value對中的value  
  25.         MessageContext mc = MessageContext.getCurrentMessageContext();  
  26.         ServiceGroupContext sgc =  mc.getServiceGroupContext();  
  27.         return (String)sgc.getProperty("login");      
  28.     }  
  29. }  


 

[java] view plaincopy
  1. package crossSession;  
  2.   
  3. import org.apache.axis2.context.MessageContext;  
  4. import org.apache.axis2.context.ServiceGroupContext;  
  5. public class SearchService  
  6. {  
  7.     public String findByName(String name)  
  8.     {  
  9.         //  第1步:獲得key-value對中的value  
  10.         MessageContext mc = MessageContext.getCurrentMessageContext();  
  11.         ServiceGroupContext sgc =  mc.getServiceGroupContext();                  
  12.         if (sgc.getProperty("login") != null)  
  13.             return "找到的數據<" + name + ">";  
  14.         else  
  15.             return "用戶未登錄";  
  16.     }  
  17. }  

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

[html] view plaincopy
  1. <serviceGroup>  
  2.     <!--  第2步:添加scope屬性,並設置屬性值爲application -->  
  3.     <service name="loginSession" scope="application">  
  4.         <description>  
  5.             登錄服務  
  6.         </description>  
  7.         <parameter name="ServiceClass">  
  8.             crossSession.LoginService  
  9.         </parameter>  
  10.         <messageReceivers>  
  11.             <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"  
  12.                 class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />  
  13.         </messageReceivers>  
  14.     </service>  
  15.     <!--  第2步:添加scope屬性,並設置屬性值爲application -->  
  16.     <service name="searchSession" scope="application">  
  17.         <description>  
  18.             搜索服務  
  19.         </description>  
  20.         <parameter name="ServiceClass">  
  21.             crossSession.SearchService  
  22.         </parameter>  
  23.         <messageReceivers>  
  24.             <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"  
  25.                 class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />  
  26.         </messageReceivers>  
  27.     </service>  
  28. </serviceGroup>  


3步與點擊打開鏈接一文中介紹的方法類似。

下面是使用兩個stub類的對象實例訪問上面實現的兩個WebService的客戶端代碼:(由於是兩個service,所以要分別實現兩個stub類)

[java] view plaincopy
  1. package crossSession;  
  2.   
  3. import java.rmi.RemoteException;  
  4.   
  5. public class LoginSearchStubClient {  
  6.   
  7.     public static void main(String[] args) throws RemoteException {  
  8.         // TODO Auto-generated method stub  
  9.         LoginSessionStub lss = new LoginSessionStub();  
  10.         LoginSessionStub.Login login = new LoginSessionStub.Login();  
  11.         LoginSessionStub.GetLoginMsg glm = new LoginSessionStub.GetLoginMsg();  
  12.         login.setUsername("bill");  
  13.         login.setPassword("1234");  
  14.         if(lss.login(login).local_return){  
  15.             System.out.println(lss.getLoginMsg(glm).get_return());  
  16.               
  17.             SearchSessionStub sss = new SearchSessionStub();  
  18.             SearchSessionStub.FindByName fbn = new SearchSessionStub.FindByName();  
  19.             fbn.setName("bill");  
  20.             System.out.println(sss.findByName(fbn).local_return);  
  21.         }  
  22.     }  
  23. }  


在執行上面的代碼後,將輸出如下的信息:

如果將scope屬性值改成transportsession,我們看看會輸出什麼!

第一:改變loginService的

     正常輸出,也就是說loginService這個服務只能在同一個服務中起作用,在這裏我們只是調用了登陸服務,所以沒影響。

第二:改變searchService的

       居然還是正常輸出,不對啊,如下代碼需要跨服務的

[java] view plaincopy
  1. if (sgc.getProperty("login") != null)  
  2.             return "找到的數據<" + name + ">";  
  3.         else  
  4.             return "用戶未登錄";  

  這是怎麼回事呢,難道問題在這裏?

[java] view plaincopy
  1. //  第1步:獲得key-value對中的value  
  2.         MessageContext mc = MessageContext.getCurrentMessageContext();  
  3.         ServiceGroupContext sgc =  mc.getServiceGroupContext(); //ServiceGroupContext而不是ServiceContext?  
[java] view plaincopy
  1. //<span style="color:black;">ServiceGroupContext與scope衝突? </span>      

好吧,既然衝突,那咱們就一個一個的試,結果更加出乎意料,把ServiceGroupContext改成ServiceContext,居然還是正常輸出,什麼情況?

這讓我開始懷疑這個程序是不是跨session的,不會是披着跨session的外衣吧,繼續研究!

先看一下scope中transportsession的問題,如下是官方文檔

Transport Session Scope
In the case of a Transport session, Axis2 uses transport-related session management techniques to manage session. As an example, in the case of HTTP, it uses HTTP cookies to manage the session. The lifetime of the session is controlled by the transport, not by Axis2; Axis2 stores the service context and serviceGroupContext in the transport session object so that the service can access those contexts as long as the session lives.
One of the key advantages of the Transport session over other sessions is that you can talk to multiple service groups within one transport session.In a SOAP session, you don't have a way to communicate between two service groups, but with the transport session you have that capability. In this case, the number of service instances created depends on the number of transport sessions created.
Deploying a service in a transport session requires you to change services.xml as follows:
<service name="foo" scope="transportsession">
</service>
If you are using Axis2 nightly builds or planning to use them the next version, deploying a service in a transport session requires additional changes to axis2.xml. That is mainly to improve the memory usage; otherwise, whether you deploy the service in a transport session or not Axis2 tries to create a session object at the transport level; with these changes, it will not create unnecessary objects. To manage the transport-level session, you need to set the manageTransportSession parameter value to true in axis2.xml:

看到這段話的時候我才感覺到transportsession不僅是單個服務那麼簡單的。

 

至於ServiceGroupContext和ServiceContext,我查了一下API文檔

可以看出來他們都是繼承自同一個類,而這個抽象類的setProperty()方法如下,

從這裏我們可以看到這個方法是用來存儲值的,至於存儲的值的訪問權限,我們只有搞清楚ServiceGroupContext和ServiceContext才能知道。

下面是ServiceContext的介紹

 

在這裏我們看到它的生命週期是不明確的,不推薦使用,而且其構造方法是可外部化的,關於這個問題,可以查看這篇文章點擊打開鏈接

 

下面是ServiceGroupContext的介紹

 

其實到這裏我還是沒多大明白ServiceGroupContext和ServiceContext的主要區別,於是我又看了MessageContext,結果又多了一個疑惑


爲什麼MessageContext只持有ServiceGroupContext,而沒有提及ServiceContext呢?

真是一波未平一波又起,看來還需要大家的智慧了,如果以上的這幾個問題有懂的高手,還請留言解決一下。





 

發佈了13 篇原創文章 · 獲贊 8 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章