Web 服务编程技巧与窍门: 在 JAX-RPC 应用程序中构建有状态会话

来源:百度文库 编辑:神马文学网 时间:2024/06/03 01:57:34

文档选项

打印本页

将此页作为电子邮件发送

样例代码
级别: 初级
Ping Wang (pacific@us.ibm.com), 咨询软件工程师, IBM
2004 年 9 月 01 日
学习如何利用 servlet 端点模型来扩展无状态 JAX-RPC Web 服务,并使用 HTTP 会话来构建有状态 Web 服务应用程序。我们用一个简单的购物车 Web 服务范例来加以说明。
Web 服务开发组对于 Web 服务本身是否为无状态存在着争论。一些开发人员提出了类似于 Web 服务资源框架(WS-Resource Framework,请参阅参考资料)那样的规范来定义有状态 Web 服务,而当前广泛使用的 JAX-RPC 规范主要处理无状态服务。 无状态的意思是,对 Web 服务的调用与之前的互操作没有相关性,并且不为以后的互操作而保存当前活动的信息。
您可以通过一些实际情况来了解无状态的含义,比如像 JavaBean 和无状态会话企业 JavaBean 组件之类的 JAX-RPC 服务端点组件并不保持状态信息。然而,您仍然可以利用基础传输协议固有的会话支持,并创建有状态 Web 服务,这取决于服务端点部署于何处。本文说明了当服务端点部署到 servlet 容器时,如何在 JAX-RPC 应用程序中使用 HTTP 的会话功能。我们将在一个简单的购物车 Web 服务中对此进行说明。
清单 1定义了一个简单的购物车 Web 服务,它允许顾客在购物车中添加、删除和查询商品条目。一个需求是该购物车需要在整个购物期间保持已选择的商品,直到顾客付款后离开。本文的其余部分说明为什么这个简单的有状态服务可以使用多种 JAX-RPC 技术来实现。
package shopping; public interface Cart extends java.rmi.Remote { public void addItem(String item) throws java.rmi.RemoteException; public void removeItem(String item) throws java.rmi.RemoteException; public int getItemNumber() throws java.rmi.RemoteException; public void checkout() throws java.rmi.RemoteException, shopping.NoUserSessionFault; }




回页首
该服务通过两个步骤实现:
实现 ServiceLifecycle 接口。 处理会话数据。
JAX-RPC 定义了一个 javax.xml.rpc.server.ServiceLifecyle 接口。如果服务实现类实现这个接口,就需要 JAX-RPC 运行时系统来管理相应的服务端点实例的生存周期。该 ServiceLifecyle 接口有两个方法: init 和 destroy 。 init 方法使用泛型类型 java.lang.Object 的“context”参数,但如果服务端点部署到基于 servlet-容器的 JAX-RPC 运行时系统,那么任何适应的 JAX-RPC 运行时系统都需要传递一个 javax.xml.rpc.server.ServletEndpointContext 实例。
在我们的范例中,服务实现类 CartSoapBindingImpl (参见清单 2)实现了这样一个 ServiceLifecyle 接口。在实现实例进行了实例化之后,JAX-RPC 运行时调用它的 init 方法将 context 参数传给类型 javax.xml.rpc.server.ServletEndpointContext 。这是可以做到的,因为购物车服务是基于 servlet 的。然后 context 对象保存为私有字段,这样后来的调用可以使用它来获取 HttpSession 。当清除时,一旦调用 destroy 方法,context 对象就被设置为 null。
public class CartSoapBindingImpl implements shopping.Cart, ServiceLifecycle { private ServletEndpointContext jaxrpcContext; public void init(Object context) throws ServiceException { jaxrpcContext = (ServletEndpointContext) context; } public void destroy() { jaxrpcContext = null; } ... }
javax.xml.rpc.server.ServletEndpointContext 接口包含几个方法。其中与本文主题有关的一个方法是 getHttpSession() ,它返回一个 javax.servlet.http.HttpSession 实例。对于每个购物车服务的方法,该方法首先针对以前缓存的 ServletEndpointContext 调用 getHttpSession 方法,以获得 HttpSession 对象。一旦 HttpSession 可用,服务实现就能够从 HttpSession 对象中检索用户会话数据,正如常规 servlet 一样(参见清单 3)。请注意,清单 3 中定义的 SessionData 类是用于保存各种购物车信息的用户自定义数据结构(点击本文顶部或底部的 code 图标)。