`
tooby
  • 浏览: 110239 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Axis2 Session管理

    博客分类:
  • Java
 
阅读更多

WebService给人最直观的感觉就是由一个个方法组成,并在客户端通过SOAP协议调用这些方法。这些方法可能有返回值,也可能没有返回值。虽然这样可以完成一些工具,但这些被调用的方法是孤立的,当一个方法被调用后,在其他的方法中无法获得这个方法调用后的状态,也就是说无法保留状态。

 

读者可以想象,这对于一个完整的应用程序,无法保留状态,就意味着只依靠WebService很难完成全部的工作。例如,一个完整的应用系统都需要进行登录,这在Web应用中使用Session来保存用户登录状态,而如果用WebService的方法来进行登录处理,无法保存登录状态是非常令人尴尬的。当然,这也可以通过其他的方法来解决,如在服务端使用static变量来保存用户状态,并发送一个id到客户端,通过在服务端和客户端传递这个id来取得相应的用户状态。这非常类似于Web应用中通过SessionCookie来管理用户状态。但这就需要由开发人员做很多工作,不过幸好Axis2为我们提供了WebService状态管理的功能。

 

使用Axis2来管理WebService的状态基本上对于开发人员是透明的。在WebService类需要使用org.apache.axis2.context.MessageContextorg.apache.axis2.context.ServiceContext类来保存与获得保存在服务端的状态信息,这些对象使用HttpSession接口的getAttributesetAttribute方法获得与设置Session域属性。

 

除此之外,还需要修改services.xml文件的内容,为<service>元素加一个scope属性,该属性有四个可取的值:Application, SOAPSession, TransportSession, Request,不过要注意一下,虽然Axis2的官方文档将这四个值的单词首字母和缩写字母都写成了大写,但经笔者测试,必须全部小写才有效,也就是这四个值应为:applicationsoapsessiontransportsessionrequest,其中requestscope属性的默认值。读者可以选择使用transportsessionapplication分别实现同一个WebService类和跨WebService类的会话管理。

 

Web服务有着很大的需 求,很多人进入了Web服务这一领域,其结果是人们需要Web服务具有更多的特性,以便使用Web服务可以完成任何事情。但Web服务从设计上来说是没有 状态的。在Web服务世界起初的时候是没有管理会话的概念的,但是现在形势改变了:没有会话管理,开发者是无法开发出高级的应用程序的。一个很好的例子是 银行系统,您登录进入系统,然后取钱,最后退出登录。
    如果我们把这一场景映射到Web服务:
    首先,用户登录进自己的账户(调用登录方法)
    用户取钱(在他的账户上调用一些操作) 
    用户退出登录(完成事务)
    您可以很容易的看出上述3个操作是相互关联的,同一个用户进行3个调用操作。所以,这意味着需要有地方来跟踪用户,另外有地方在用户调用方法期间跟踪用户数据。这也就暗含了需要会话管理。
    当开发高级应用程序时,我们必须打破现有的规则;否则,没有人能够开发出真正的Web应用程序。虽然Web服务本质上是无状态的,但是需要在Web服务之上增加一层会话管理的功能。 


    Axis2的无状态本质
    Axis2的优秀设计原则之一是保持逻辑和状态的分离,所以它没有组件需要维护会话,实际上也是这样做的。在Axis2的处理程序中,传输部分,甚至Aixs引擎部分都是无状态的。因此,对Axis2来说多个实例和一个实例是没有区别的。
    作为最佳实践,处理程序或传输部分不应该保持任何实例变量(如果可能会变化的话),因为那样会打破Axis2无状态的本质。所以,如果处理程序或传输部分需要有状态的方式,正确的做法是在需要的时候保存状态和Axis2的状态层次,而不是保持实例变量。

 
    Axis2的会话类型
    像上面提到的,企业级Web服务无法得到认可除非引在Web服务引擎中入了会话概念。换种说法,因为存在不需要维持会话的Web服务,让每种Web服务引擎都支持会话管理这样的说法是不对的。一个很好的例子是Google搜索服务和Google拼写检查服务。
    会话管理的直接影响是占用内存空间的上升和性能的降低,所以您需要一个折中:您的服务是否要支持会话并提供状态。Axis2是定位于企业级Web服务引擎的,所以它必须提供会话管理。
    有几种类型的会话,它们的生命周期是各不相同的。有些会话存在几秒钟,而有些会话的生命周期和系统一样长。Axis2设计为支持4种类型会话,它们存在很多差别,希望您能够使用以下4种会话类型开发出各种Web服务。
    Request
    SOAPSession
    Application
    Transport


    Axis2的上下文层次结构
    在深入讨论Axis2的会话之前,理解Axis2的各种上下文是很有帮助的。如上所述,Axis2保持逻辑和状态的分离,上下文是保存状态的地方。在Axis2中有5种类型的上下文:
ConfigurationContext:整个系统运行时的表述,为了启动Axis2系统需要有一个配置上下文。配置上下文与系统的生命周期是一样的,在这里保存一些状态(配置项)能够一直有效(直到系统关闭)。
ServiceGroupContext:在Axis2中,可以在一个服务组中部署多个服务。在运行时,有一个或多个服务组(依赖于组的会话范围)上下文在会话范围内保存组的状态。
ServiceContext:表述一个服务的运行时状态,其生命周期与会话的生命周期相同。依赖于所对应服务的会话范围,存在一个或多个服务上下文。
OperationContext:表述MEP(Message Exchange Patterns,消息交换格式)的生命周期。操作上下文的生命周期通常短于服务上下文的生命周期。
MessageContext:表述所输入消息的生命周期。如果给定执行链中的两个处理程序想共享数据,最好的方法是把他们存在消息上下文中。一个操作上下文可能有多个消息上下文。
    与会话范围无关,当会话开始和结束时,Axis2会通知服务的实现类,但是需要在服务的实现类中增加两个方法。 

  1. public void init(ServiceContext serviceContext) {   
  2. }   
  3.   
  4. public void destroy(ServiceContext serviceContext) {   
  5. }   

    除此之外,当服务接收到一个请求时,它会传入相应的操作上下文作为参数进行通知。如果服务想访问输入消息的上下文或输入的SOAP消息,可以在服务的实现类中加入以下方法来做到这一点,在真正的方法调用之前调用这一方法。 

  1. public void setOperationContext(OperationContext operationContext) {   
  2. }   

   

    请求会话范围(Request Session Scope)
    请求会话是Axis2默认的会话类型,部署服务时没有指定会话管理的内容,服务会被部署为请求会话类型。这种会话的生命周期被限定在方法调用的生命周期之内,或者请求的处理时间内。所以,当部署服务为请求范围的服务时,是没法管理会话的;这与没有会话是一样的。
    一旦把服务部署为请求会话范围的服务时,每个服务的实现类就会准备建立服务实例。例如以请求范围的方式建立了一个名为“foo”的服务,如果客户端调用了 10次,就会有这个服务实现类的10个实例。如果想显式的指定服务的会话范围,可以在services.xml中的service标签中增加一个 scope属性,如下:
<service name="foo" scope="request">
</service>
    即使把服务部署为请求范围内的,在Axis2中也有一些方法管理会话。一种方法是在Axis2的全局运行时(配置上下文)中保存状态,在需要的时候获取它。


    SOAP会话范围(SOAP Session Scope)
    SOAP会话的生命周期比请求会话的稍长,以SOAP会话的方式部署服务需要修改services.xml。管理SOAP会话需要客户端和服务都能识别会话,换句话说,客户端访问相同会话需要传输会话相关的数据,服务需要以会话相关的数据来验证用户。
    管理SOAP会话,客户端需要在SOAP头中增加名为“serviceGroupId”的参数。SOAP会话不仅提供一个服务调用的会话,还提供一个服务 组中多个服务的会话。只要在同一个SOAP会话中,可以在服务上下文中管理服务相关的数据;如果想在组中多个服务中共享数据,可以使用服务组上下文。
    以SOAP会话的方式部署了服务,当客户端第一次访问服务的时候,Axis2会产生“serviceGroupId”,并在wsa:ReplyTo中以引用参数的方式向客户端传输: 

  1. <wsa:ReplyTo>   
  2.   <wsa:Address>   
  3.   http://www.w3.org/2005/08/addressing/anonymous   
  4.   </wsa:Address>   
  5.   <wsa:ReferenceParameters>   
  6.     <axis2:ServiceGroupId xmlns:axis2=   
  7.       "http://ws.apache.org/namespaces/axis2">   
  8.         urn:uuid:65E9C56F702A398A8B11513011677354   
  9.     </axis2:ServiceGroupId>   
  10.   </wsa:ReferenceParameters>   
  11. </wsa:ReplyTo>   

   如果客户端想保持在同一个会话内,它要复制那个引用参数,并在第二次调用服务的时候传回服务器。只要客户端传输了正确的 “serviceGroupId”,它就会在同一个会话内,服务也可以维护会话相关的数据。与请求会话不同,SOAP有默认的失效期,如果客户端超过30 秒没有连接服务,会话就会过期。如果客户端发送了过期的“serviceGroupId”,会得到Axis错误。
    管理SOAP会话需要衔接服务端和客户端的对应模块。部署服务为SOAP会话方式需要以如下方式修改services.xml:

  1. <service name="foo" scope="soapsession"> </service>   


    传输会话范围(Transport Session Scope)
    在传输会话方式下,Axis2以传输相关的会话管理技术来管理会话。例如,在HTTP协议下,以HTTP cookies的方式来管理会话。会话的生命周期是由传输来控制的,而不是Axis2;Axis2在传输会话内保存服务上下文和服务组上下文,所以在会话 生命期内服务都可以访问这些上下文。
    传输会话的主要优势是在一个会话内与多个服务组交互。在SOAP会话中,无法在两个服务组间进行交互,而在传输会话中就可以。这种情况下,服务实例的数量取决于传输会话的数量。
    部署服务为传输会话方式需要以如下方式修改services.xml: 

  1. <service name="foo" scope="transportsession"> </service>   

    如果打算使用 Axis2,以传输会话方式部署服务需要对axis2.xml做些修改。这主要是为了提高内存的使用率;否则,无论是否以传输会话方式部署服 务,Axis2都会在传输的级别建立会话对象;有了这些变化,Axis就不会创建无用的对象了。为了管理传输级别的会话,需要在axis2.xml中设置 “manageTransportSession”参数为“true”: 

  1. <parameter name="manageTransportSession" locked="false">true</parameter>   


    应用范围(Application Scope)
    应用范围的会话与其他会话方式相比具有最长的生命周期,应用会话的生命周期与系统的生命周期一样长。如果以应用范围会话的方式部署服务,只会有服务的一个 实例,并且这个服务只有一个服务上下文。在Axis2中,如果考虑内存占用,并且不想管理会话,一个好的方法是把服务部署为应用范围的。
    当把服务部署为应用范围的会话方式时,客户端不需要传送额外的数据以使用同一个会话。部署服务为应用范围会话方式需要以如下方式修改services.xml: 

  1. <service name="foo" scope="application"> </service>   


    服务客户端管理会话
    客户端管理会话需要做一些工作。如上所述,客户端如果想在SOAP会话和传输会话方式下保持在同一个会话中,需要传输一些会话相关的数据。对SOAP会话来说,需要复制所需的引用参数;对传输会话来说,需要访问传输以复制和发送cookies。
    为了简化开发,Axis2有内置的管理会话的功能,在客户端设置一个标志就可以了。这样,只要使用同一个客户端,就会往服务端发送会话相关的数据。所以,如果想保持在同一个会话内,最主要的一点就是使用同一个客户端调用服务。
    如果想保持在同一个会话内,可以用以下的方式创建服务客户端,并且重用客户端对象调用服务。 

  1. Options options = new Options();   
  2. options.setManageSession(true);   
  3. ServiceClient sender = new ServiceClient();   
  4. sender.setOptions(options);   


    一旦按照如上方式创建了服务客户端,如果服务部署为SOAP会话方式,客户端会复制“serviceGroupId”并在第二次调用的时候上传服务端;如 果服务器是发送的会话id,例如HTTP cookies,客户端就会复制服务上下文(在客户端)并在第二次调用的时候发送给服务器。


    总结
    无状态是Web服务的主要特性之一,但这对高级Web服务开发来说是一个限制。使用Web服务开发企业级的应用并不容易,除非有一个会话管理层。Axis2有4中会话类型以解决企业级服务开发的问题。

 

在客户端需要使用setManageSession(true)打开Session管理功能。

综上所述,实现同一个WebServiceSession管理需要如下三步:

1. 使用MessageContextServiceContext获得与设置key-value对。

2. 为要进行Session管理的WebService类所对应的<service>元素添加一个scope属性,并将该属性值设为transportsession

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

下面是一个在同一个WebService类中管理Session的例子。

先建立一个WebService类,代码如下:

  1. package service;  
  2. import org.apache.axis2.context.ServiceContext;  
  3. import org.apache.axis2.context.MessageContext;    
  4. public class LoginService {  
  5.        public boolean login(String username, String password) {  
  6.               if("bill".equals(username) && "1234".equals(password)) {  
  7.                      //  第1步:设置key-value对  
  8.                      MessageContext mc = MessageContext.getCurrentMessageContext();  
  9.                      ServiceContext sc = mc.getServiceContext();  
  10.                      sc.setProperty("login""成功登录");      
  11.                      return true;  
  12.               } else {  
  13.                      return false;  
  14.               }  
  15.        }  
  16.        public String getLoginMsg() {  
  17.               //  第1步:获得key-value对中的value  
  18.               MessageContext mc = MessageContext.getCurrentMessageContext();  
  19.               ServiceContext sc = mc.getServiceContext();  
  20.               return (String)sc.getProperty("login");      
  21.        }  
  22. }  

LoginService类中有两个方法:logingetLoginMsg,如果login方法登录成功,会将“成功登录”字符串保存在ServiceContext对象中。如果在login方法返回true后调用getLoginMsg方法,就会返回“成功登录”。

    下面是LoginService类的配置代码(services.xml):

  1. <!--  第2步:添加scope属性  -->  
  2. <service name="loginService" scope="transportsession">  
  3.        <description>  
  4.               登录服务  
  5.        </description>  
  6.        <parameter name="ServiceClass">  
  7.               service.LoginService  
  8.        </parameter>  
  9.        <messageReceivers>  
  10.               <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"  
  11.                      class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />  
  12.        </messageReceivers>  
  13. </service>  

使用如下的命令生成客户端使用的stub类:

  1. %AXIS2_HOME%\bin\wsdl2java   
  2.   
  3. -uri http://localhost:8080/axis2/services/loginService?wsdl -p client -s -o stub  
  4.   
  5. %AXIS2_HOME%\bin\wsdl2java   
  6.   
  7. -uri http://localhost:8080/axis2/services/loginService?wsdl   
  8.   
  9. -p client -s -o D:/Work/NPU/Develop/eclipse-workspace/SayHello/src  

    stub\src\client目录中生成了一个LoginServiceStub.java类,在该类中找到如下的构造句方法:

  1. public LoginServiceStub(  
  2.   
  3. org.apache.axis2.context.ConfigurationContext configurationContext,  
  4. java.lang.String targetEndpoint, boolean useSeparateListener)  
  5. throws org.apache.axis2.AxisFault  {  
  6.            
  7.        _serviceClient.getOptions().setSoapVersionURI(  
  8.       org.apache.axiom.soap.SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);  
  9. }  

在该方法中最后添加如下的代码(在Axis1.5以上版本中不需要这么做)

  1. //  第3步:打开客户端的Session管理功能  
  2. _serviceClient.getOptions().setManageSession(true);  

下面的客户端代码使用LoginServiceStub对象访问了刚才建立的WebService

  1. LoginServiceStub stub = new LoginServiceStub();  
  2. LoginServiceStub.Login login = new LoginServiceStub.Login();  
  3. login.setUsername("bill");  
  4. login.setPassword("1234");  
  5. if(stub.login(login).local_return) {  
  6.        System.out.println(stub.getLoginMsg().local_return);  
  7. }  

运行上面的代码后,会输出“成功登录”信息。

分享到:
评论

相关推荐

    axis2+spring webservice

    简单例子:axis2整合spring发布webservice,以及session的管理

    WebService大讲堂之Axis2系列教程

    Axis2是目前比较流行的WebService引擎。...本课程站在初学者角度介绍了Axis2的大多数常用的功能,例如,以多种方式编写和发布WebService、JAX-RPC、JAX-WS、复杂类型传输、WebService会话管理、Axis2模块等

    axis2;WebService

    Axis WebService会话Session的管理 Axis用控制台Dos命令发布WebService Axis跨多个WebService管理Session Axis用Spring的JavaBean发布WebService Axis异步调用WebService Axis 的Module模块 Axis使用SoapMonitar监视...

    axis2_WebService_开发指南

    Axis WebService 会话Session 的管理 Axis 用控制台Dos 命令发布WebService Axis 跨多个WebService 管理Session Axis 用Spring 的JavaBean 发布WebService Axis 异步调用WebService Axis 的Module 模块 Axis 使用...

    axis2新手教程

    axis2中service.xml,session管理,module扩展

    axis2教程及案例

    比较全面的讲解了axis2安装、开发、布署,以及session管理,soap模块监视等,附带案例,亲测无误!

    axis2-1.4.1及教程

    1):用POJO实现0配置的WebService 2):复合类型数据的传递 3):使用services.xml文件发布WebService 4):二进制文件传输 ...9):编写Axis2模块(Module) 10):使用soapmonitor模块监视soap请求与响应消息

    axis2 教程_个人备用文档

    1. 用POJO实现0配置的WebService 2. 复合类型数据的传递 3. 使用services.xml文件发布WebService 4.... 5. 会话(Session)管理 ... 编写Axis2模块(Module) 10. 使用soapmonitor模块监视soap请求与响应消息

    Axis2教程 包含描述目录的内容

    WebService大讲堂之Axis2系列教程 1. 用POJO实现0配置的WebService 2. 复合类型数据的传递 3. 使用services.xml文件发布WebService 4. 二进制文件传输 5. 会话(Session)管理 6. 跨服务会话(Session)管理 ...

    axis2_webservice

    Axis的简单准备 Axis的入门实例 ...Axis跨多个WebService管理Session Axis用Spring的JavaBean发布WebService Axis异步调用WebService Axis的Module模块 Axis使用SoapMonitar监视WebService的请求和响应信息

    webservice6 跨越session管理

    webservice6 跨越session管理

    Axis2 WebService 开发指南 技术文档 入门文档

    Axis WebService会话Session的管理 Axis用控制台Dos命令发布WebService Axis跨多个WebService管理Session Axis用Spring的JavaBean发布WebService Axis异步调用WebService Axis 的Module模块 Axis使用...

    AXIS2大讲堂文档

    文档1 pojo实现0配置 文档2 符合数据类型 文档3 使用services.xml发布...文档6 跨越session管理 文档7 spring的bean发布为webservice 文档8 异步调用webservice 文档9 编写axis模块 文档10 使用moniter监视器

    axis2编写发布和例子详解

    axis2入门学习资料,通过10个步骤详细例子(测试都能运行),简单阐述了ajax通过tomcat发布方法,session管理,异步调用和同步调用,spring整合等功能,说明,配置比较详细

    WebService大讲堂之Axis2

    WebService大讲堂之Axis2(5):会话(Session)管理 .................................................................................... 20 WebService大讲堂之Axis2(6):跨服务会话(Session)管理 ...............

    编程入门_Eclipse教程

    3.1.3. WebService会话Session的管理 24 3.1.4. 用Spring创建的JavaBean发布成WebService 29 3.1.5. 异步调用WebService 32 4. Eclipse中安装 Lomboz 35 4.1. 持久化对象与OID 35 4.1.1. 对持久化对象的要求 35 ...

    在Web Services中管理Sessions

    在Web Services中管理Sessions 在Web service中通常采用两种公认技术来管理session,一种是借助HTTP和HTTP cookies,另一种是用SOAP headers。Axis能帮你实现这两种技术。

    java开源包2

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    JAVA上百实例源码以及开源项目源代码

    2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...

Global site tag (gtag.js) - Google Analytics