WebService给人最直观的感觉就是由一个个方法组成,并在客户端通过SOAP协议调用这些方法。这些方法可能有返回值,也可能没有返回值。虽然这样可以完成一些工具,但这些被调用的方法是孤立的,当一个方法被调用后,在其他的方法中无法获得这个方法调用后的状态,也就是说无法保留状态。
读者可以想象,这对于一个完整的应用程序,无法保留状态,就意味着只依靠WebService很难完成全部的工作。例如,一个完整的应用系统都需要进行登录,这在Web应用中使用Session来保存用户登录状态,而如果用WebService的方法来进行登录处理,无法保存登录状态是非常令人尴尬的。当然,这也可以通过其他的方法来解决,如在服务端使用static变量来保存用户状态,并发送一个id到客户端,通过在服务端和客户端传递这个id来取得相应的用户状态。这非常类似于Web应用中通过Session和Cookie来管理用户状态。但这就需要由开发人员做很多工作,不过幸好Axis2为我们提供了WebService状态管理的功能。
使用Axis2来管理WebService的状态基本上对于开发人员是透明的。在WebService类需要使用org.apache.axis2.context.MessageContext和org.apache.axis2.context.ServiceContext类来保存与获得保存在服务端的状态信息,这些对象使用HttpSession接口的getAttribute和setAttribute方法获得与设置Session域属性。
除此之外,还需要修改services.xml文件的内容,为<service>元素加一个scope属性,该属性有四个可取的值:Application, SOAPSession, TransportSession, Request,不过要注意一下,虽然Axis2的官方文档将这四个值的单词首字母和缩写字母都写成了大写,但经笔者测试,必须全部小写才有效,也就是这四个值应为:application、soapsession、transportsession、request,其中request为scope属性的默认值。读者可以选择使用transportsession和application分别实现同一个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会通知服务的实现类,但是需要在服务的实现类中增加两个方法。
- public void init(ServiceContext serviceContext) {
- }
- public void destroy(ServiceContext serviceContext) {
- }
除此之外,当服务接收到一个请求时,它会传入相应的操作上下文作为参数进行通知。如果服务想访问输入消息的上下文或输入的SOAP消息,可以在服务的实现类中加入以下方法来做到这一点,在真正的方法调用之前调用这一方法。
- public void setOperationContext(OperationContext operationContext) {
- }
请求会话范围(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中以引用参数的方式向客户端传输:
- <wsa:ReplyTo>
- <wsa:Address>
- http://www.w3.org/2005/08/addressing/anonymous
- </wsa:Address>
- <wsa:ReferenceParameters>
- <axis2:ServiceGroupId xmlns:axis2=
- "http://ws.apache.org/namespaces/axis2">
- urn:uuid:65E9C56F702A398A8B11513011677354
- </axis2:ServiceGroupId>
- </wsa:ReferenceParameters>
- </wsa:ReplyTo>
如果客户端想保持在同一个会话内,它要复制那个引用参数,并在第二次调用服务的时候传回服务器。只要客户端传输了正确的 “serviceGroupId”,它就会在同一个会话内,服务也可以维护会话相关的数据。与请求会话不同,SOAP有默认的失效期,如果客户端超过30 秒没有连接服务,会话就会过期。如果客户端发送了过期的“serviceGroupId”,会得到Axis错误。
管理SOAP会话需要衔接服务端和客户端的对应模块。部署服务为SOAP会话方式需要以如下方式修改services.xml:
- <service name="foo" scope="soapsession"> </service>
传输会话范围(Transport Session Scope)
在传输会话方式下,Axis2以传输相关的会话管理技术来管理会话。例如,在HTTP协议下,以HTTP cookies的方式来管理会话。会话的生命周期是由传输来控制的,而不是Axis2;Axis2在传输会话内保存服务上下文和服务组上下文,所以在会话 生命期内服务都可以访问这些上下文。
传输会话的主要优势是在一个会话内与多个服务组交互。在SOAP会话中,无法在两个服务组间进行交互,而在传输会话中就可以。这种情况下,服务实例的数量取决于传输会话的数量。
部署服务为传输会话方式需要以如下方式修改services.xml:
- <service name="foo" scope="transportsession"> </service>
如果打算使用 Axis2,以传输会话方式部署服务需要对axis2.xml做些修改。这主要是为了提高内存的使用率;否则,无论是否以传输会话方式部署服 务,Axis2都会在传输的级别建立会话对象;有了这些变化,Axis就不会创建无用的对象了。为了管理传输级别的会话,需要在axis2.xml中设置 “manageTransportSession”参数为“true”:
- <parameter name="manageTransportSession" locked="false">true</parameter>
应用范围(Application Scope)
应用范围的会话与其他会话方式相比具有最长的生命周期,应用会话的生命周期与系统的生命周期一样长。如果以应用范围会话的方式部署服务,只会有服务的一个 实例,并且这个服务只有一个服务上下文。在Axis2中,如果考虑内存占用,并且不想管理会话,一个好的方法是把服务部署为应用范围的。
当把服务部署为应用范围的会话方式时,客户端不需要传送额外的数据以使用同一个会话。部署服务为应用范围会话方式需要以如下方式修改services.xml:
- <service name="foo" scope="application"> </service>
服务客户端管理会话
客户端管理会话需要做一些工作。如上所述,客户端如果想在SOAP会话和传输会话方式下保持在同一个会话中,需要传输一些会话相关的数据。对SOAP会话来说,需要复制所需的引用参数;对传输会话来说,需要访问传输以复制和发送cookies。
为了简化开发,Axis2有内置的管理会话的功能,在客户端设置一个标志就可以了。这样,只要使用同一个客户端,就会往服务端发送会话相关的数据。所以,如果想保持在同一个会话内,最主要的一点就是使用同一个客户端调用服务。
如果想保持在同一个会话内,可以用以下的方式创建服务客户端,并且重用客户端对象调用服务。
- Options options = new Options();
- options.setManageSession(true);
- ServiceClient sender = new ServiceClient();
- sender.setOptions(options);
一旦按照如上方式创建了服务客户端,如果服务部署为SOAP会话方式,客户端会复制“serviceGroupId”并在第二次调用的时候上传服务端;如 果服务器是发送的会话id,例如HTTP cookies,客户端就会复制服务上下文(在客户端)并在第二次调用的时候发送给服务器。
总结
无状态是Web服务的主要特性之一,但这对高级Web服务开发来说是一个限制。使用Web服务开发企业级的应用并不容易,除非有一个会话管理层。Axis2有4中会话类型以解决企业级服务开发的问题。
在客户端需要使用setManageSession(true)打开Session管理功能。
综上所述,实现同一个WebService的Session管理需要如下三步:
1. 使用MessageContext和ServiceContext获得与设置key-value对。
2. 为要进行Session管理的WebService类所对应的<service>元素添加一个scope属性,并将该属性值设为transportsession。
3. 在客户端使用setManageSession(true)打开Session管理功能。
下面是一个在同一个WebService类中管理Session的例子。
先建立一个WebService类,代码如下:
- package service;
- import org.apache.axis2.context.ServiceContext;
- import org.apache.axis2.context.MessageContext;
- public class LoginService {
- public boolean login(String username, String password) {
- if("bill".equals(username) && "1234".equals(password)) {
- // 第1步:设置key-value对
- MessageContext mc = MessageContext.getCurrentMessageContext();
- ServiceContext sc = mc.getServiceContext();
- sc.setProperty("login", "成功登录");
- return true;
- } else {
- return false;
- }
- }
- public String getLoginMsg() {
- // 第1步:获得key-value对中的value
- MessageContext mc = MessageContext.getCurrentMessageContext();
- ServiceContext sc = mc.getServiceContext();
- return (String)sc.getProperty("login");
- }
- }
在LoginService类中有两个方法:login和getLoginMsg,如果login方法登录成功,会将“成功登录”字符串保存在ServiceContext对象中。如果在login方法返回true后调用getLoginMsg方法,就会返回“成功登录”。
下面是LoginService类的配置代码(services.xml):
- <!-- 第2步:添加scope属性 -->
- <service name="loginService" scope="transportsession">
- <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>
使用如下的命令生成客户端使用的stub类:
- %AXIS2_HOME%\bin\wsdl2java
- -uri http://localhost:8080/axis2/services/loginService?wsdl -p client -s -o stub
- %AXIS2_HOME%\bin\wsdl2java
- -uri http://localhost:8080/axis2/services/loginService?wsdl
- -p client -s -o D:/Work/NPU/Develop/eclipse-workspace/SayHello/src
在stub\src\client目录中生成了一个LoginServiceStub.java类,在该类中找到如下的构造句方法:
- public LoginServiceStub(
- org.apache.axis2.context.ConfigurationContext configurationContext,
- java.lang.String targetEndpoint, boolean useSeparateListener)
- throws org.apache.axis2.AxisFault {
- _serviceClient.getOptions().setSoapVersionURI(
- org.apache.axiom.soap.SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
- }
在该方法中最后添加如下的代码(在Axis1.5以上版本中不需要这么做):
- // 第3步:打开客户端的Session管理功能
- _serviceClient.getOptions().setManageSession(true);
下面的客户端代码使用LoginServiceStub对象访问了刚才建立的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);
- }
运行上面的代码后,会输出“成功登录”信息。
相关推荐
描述中提到的“简单例子:axis2整合spring发布webservice”,意味着我们将学习如何将这两个框架结合,以便通过Spring来管理和控制Web服务的生命周期,同时利用Axis2的Web服务处理能力。此外,“以及session的管理”...
本教程旨在全面介绍Axis2的安装、开发、部署,以及如何进行session管理和SOAP模块监控,通过实战案例帮助你深入理解和应用Axis2。 1. **Axis2安装**:首先,你需要下载适合你操作系统的Axis2版本,然后解压到指定...
* Session 管理:Axis2 提供了 Session 管理机制,使得开发者可以轻松地管理 Session。 * SoapMonitar 监视:Axis2 提供了 SoapMonitar 监视机制,使得开发者可以监视 WebService 的请求和响应信息。 * 异步调用:...
### Axis2教程知识点详解 #### 一、Axis2概述及应用场景 - **定义与特性**:Axis2是一款基于Apache组织的开源WebService引擎,是Axis1.x的后续版本,旨在提供更为强大且灵活的服务架构。它支持SOAP 1.1和SOAP 1.2...
Session管理** - **单个WebService**:通过配置文件`axis2.xml`中`sessionManager`元素来管理会话。 - **跨多个WebService**:使用统一的会话管理机制,确保不同服务间共享会话数据。 ##### **3. 异步调用** ...
标题中的“在自己的项目中利用axis2+spring发布webservice与客户端调用包括session”指出的是一个关于在实际项目开发中如何使用Axis2和Spring框架来发布Web服务,并且涉及了Web服务客户端调用以及会话(session)...
### Axis2核心功能详解 #### 一、Axis2概述及特点 - **支持标准全面**:Axis2不仅支持SOAP 1.1和SOAP 1.2标准,还集成了流行的RESTful Web Service,并且兼容Spring框架和JSON技术,极大地拓宽了其应用场景。 - **...
**WebService会话Session管理** - Axis2支持在不同Web服务间管理会话,这对于需要跨服务共享状态的应用程序非常重要。 **控制台命令发布WebService** - 通过命令行工具,如`wsdl2java`和`java2wsdl`,可以在没有...
此外,Axis2还提供了辅助工具来发布和调用WebService,以及管理WebService会话(Session)。会话管理在处理有状态的服务时尤为重要。 在某些情况下,可能会需要使用控制台命令(如Dos命令)来发布WebService,Axis2...
本文将深入探讨在Axis2框架下实现跨服务Session管理的原理和步骤。 首先,我们要理解什么是Session。在Web开发中,Session是服务器用来存储特定用户会话信息的一种机制。通常,Session用于跟踪用户状态,比如用户...
- 使用Axis2的管理界面,选择发布服务选项,并指定相应的类路径。 3. **测试WebService:** - 使用Axis2的管理界面查看已发布的服务列表。 - 调用 `getGreeting` 和 `getPrice` 方法以验证服务是否正确运行。 #...
本教程面向初学者,旨在详细介绍Axis2的核心功能和应用场景,包括使用POJO实现无配置的Web服务、处理复合类型数据、通过services.xml文件发布Web服务、二进制文件传输、会话管理以及跨服务会话管理等。 1. **用POJO...
4. **WebService会话管理**:会话管理在保持用户状态和服务交互连续性方面至关重要,课程会介绍如何在Axis2中实现和维护会话。 5. **Axis2模块**:模块是Axis2中的一个重要概念,它们允许你扩展Axis2的功能,比如...
5. **会话(Session)管理**:Axis2提供了会话管理机制,允许在Web Services之间保持状态,这对于实现交互式服务和跨服务通信很有帮助。 6. **跨服务会话管理**:扩展了会话管理功能,使得可以在多个服务之间共享...
Axis2 提供了 Session 管理机制,可以管理多个 WebService 的会话,实现了会话的复用和共享。 7. Axis2 的异步调用: Axis2 支持异步调用,可以实现异步调用 WebService,提高系统的性能和可扩展性。 8. Axis2 ...
Axis2 提供了对 WebService 会话(Session)的管理,允许在多个请求之间保持状态。 #### 3.3 跨多个 WebService 管理 Session 通过特定机制,如使用 Cookie 或 SOAP Header,可以在多个 WebService 间共享 Session...
- **步骤**:使用Spring框架管理的JavaBean通过Axis2发布为WebService。 ##### 8. 异步调用WebService - **概念**:发送请求后不等待响应即可继续执行其他操作。 - **实现**:通过异步调用接口或回调机制实现。 #...