内容


Web 服务编程技巧与窍门

在 JAX-RPC 应用程序中构建有状态会话

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: 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 技术来实现。

清单 1. 购物车接口
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;
}

服务的实现

该服务通过两个步骤实现:

  1. 实现 ServiceLifecycle 接口。
  2. 处理会话数据。

实现 ServiceLifecyle 接口

JAX-RPC 定义了一个 javax.xml.rpc.server.ServiceLifecyle 接口。 如果服务实现类实现这个接口,就需要 JAX-RPC 运行时系统来管理相应的服务端点实例的生存周期。该 ServiceLifecyle 接口有两个方法: initdestroyinit 方法使用泛型类型 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。

清单 2. 实现 ServiceLifecycle 接口
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 图标)。

清单 3. 从 ServletEndpointContext 中检索 HTTPSession
public class CartSoapBindingImpl implements shopping.Cart, ServiceLifecycle {   
    private ServletEndpointContext jaxrpcContext;    
    ...
    
    public void addItem(java.lang.String item)
        throws java.rmi.RemoteException {
        getSessionData().addItem(item);
    }
    // SessionData is a utility class to store all the shopping cart related information
    private SessionData getSessionData() {
        SessionData sd = (SessionData) 
        	
        jaxrpcContext.getHttpSession().getAttribute(SessionData.SESSION_KEY);
        if(sd == null) {
            sd = new SessionData();
            
        jaxrpcContext.getHttpSession().setAttribute(SessionData.SESSION_KEY, sd);
        }
        return sd;        
    }    
    ...
}

客户端的启用

与自动处理会话的典型 Web 浏览器不同的是,JAX-RPC 客户端并不缺省的使用目标服务端点参与会话。因为这一点,参与会话的客户端必须明确的将一个专门的存根属性( javax.xml.rpc.Stub.SESSION_MAINTAIN_PROPERTY 或者 " javax.xml.rpc.session.maintain ")设置为 true,这样 JAX-RPC 客户端运行时将维护调用客户端的会话(参见 清单 4)。否则,服务端点获取的 HttpSession 对象将为空,或者各个服务调用的 HttpSession 很可能不一致。

请注意 JAX-RPC 客户端的定义是相对于服务的,这些服务与客户端进行通信,并且不同服务的存根被认为是不同的客户端。同样,即使存根可能与运行在相同后端服务器的服务进行对话,典型的 JAX-RPC 运行时也分别为每个单独的存根维护会话数据。因此,如果您编写应用程序来调用两个不同的服务,就不应该期望能够跨这两个服务调用来对会话进行维护。

清单 4. 要求 JAX-RPC 运行时维护会话
	javax.xml.rpc.Stub jaxrpcStub = (javax.xml.rpc.Stub) getVendorSpecificStub();
	jaxrpcStub._setProperty(javax.xml.rpc.Stub.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE);

结束语

即使基于 JAX-RPC 的 Web 服务本身是无状态的,您仍然可以使用 servlet 容器提供的会话支持并采用特定的服务端点模型(比如基于 servlet 的端点)来构建有状态 Web 服务应用程序。同时,客户端也需要切换一个特定的标志来通知 JAX-RPC 运行时系统对客户端会话进行维护。


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=SOA and web services
ArticleID=23168
ArticleTitle=Web 服务编程技巧与窍门: 在 JAX-RPC 应用程序中构建有状态会话
publish-date=09012004