在《WebService大講堂之Axis2(5):會話(Session)管理》一文中介紹了如何使用Axis2來管理同一 個服務的會話,但對於一個復雜的系統,不可能只有一個WebService服務,例如,至少會有一個管理用戶 的WebService(用戶登錄和注冊)以及處理業務的WebService。象這種情況,就必須在多個WebService服 務之間共享會話狀態,也稱為跨服務會話(Session)管理。實現跨服務會話管理與實現同一個服務的會話 管理的步驟類似,但仍然有一些差別,實現跨服務會話管理的步驟如下:
實現跨服務的Session管理需要如下三步:
1.使用MessageContext和ServiceGroupContext獲得與設置key-value對。
2.為要進行Session管理的WebService類所對應的<service>元素添加一個scope屬性,並將該屬 性值設為application。
3.在客戶端使用setManageSession(true)打開Session管理功能。
從上面的步驟可以看出,實現跨服務會話管理與實現同一個服務的會話管理在前兩步上存在著差異, 而第3步是完全一樣的。下面是一個跨服務的會話管理的實例。在這個例子中有兩個WebService類: LoginService和SearchService,代碼如下:
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步:設置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 "找到的數據<" + name + ">"; else return "用戶未登錄"; } }
services.xml文件中的配置代碼如下:
<serviceGroup> <!-- 第2步:添加scope屬性,並設置屬性值為application --> <service name="loginService" scope="application"> <description> 登錄服務 </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屬性,並設置屬性值為application --> <service name="searchService" scope="application"> <description> 搜索服務 </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類的對象實例訪問上面實現的兩個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); }
在執行上面的代碼後,將輸出如下的信息:
成功登錄
找到的數據<abc>
讀者可以將scope屬性值改成transportsession,看看會輸出什麼!
實際上,Axis2的會話管理也是通過Cookie實現的,與Web應用中的Session管理類似。如果讀者使用C# 訪問支持會話(在同一個服務中的會話管理)的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);
}
如果是訪問跨服務的支持會話的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版本請讀者自行測試)調用支持會話 的WebService時有一些差別。經筆者測試,使用delphi調用WebService,將scope屬性值設為 transportsession和application都可以實現跨服務的會話管理,這一點和Java與C#不同,Java和C#必須 將scope屬性值設為application才支持跨服務會話管理。在delphi中不需要象C#指定一個 CookieContainer或其他類似的對象,而只需要象訪問普通的WebService一樣訪問支持會話的WebService 即可。