跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

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

Ping Wang (pacific@us.ibm.com), 咨询软件工程师, IBM
Ping Wang
Ping Wang 是 IBM WebSphere Web 服务引擎的开发人员之一,他是 WebSphere System Management 的开发者,并专注于如何使用 JMX(Java Management eXtension)管理分布式流程。您可以通过 pacific@us.ibm.com 与 Ping 联系。

简介: 学习如何利用 servlet 端点模型来扩展无状态 JAX-RPC Web 服务,并使用 HTTP 会话来构建有状态 Web 服务应用程序。我们用一个简单的购物车 Web 服务范例来加以说明。

发布日期: 2004 年 9 月 01 日
级别: 初级
访问情况 : 1012 次浏览
评论: 


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 运行时系统对客户端会话进行维护。



下载

名字大小下载方法
ws-statefulcode.earHTTP

关于下载方法的信息


参考资料

关于作者

Ping Wang

Ping Wang 是 IBM WebSphere Web 服务引擎的开发人员之一,他是 WebSphere System Management 的开发者,并专注于如何使用 JMX(Java Management eXtension)管理分布式流程。您可以通过 pacific@us.ibm.com 与 Ping 联系。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

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
author1-email=pacific@us.ibm.com
author1-email-cc=

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。