Sun ONE logo上一部分 | 目录 | 索引 | 下一部分
Sun ONE Application Server 7 Enterprise Java Bean 技术开发者指南



使用 Bean

本节介绍在 Sun ONE Application Server 7 中创建会话 Bean 的准则。



注意

如果您不熟悉会话 Bean 或 EJB 技术,请参阅 Java 软件指南:

http://java.sun.com/j2ee/docs.html

关于会话 Bean 的详细信息包含在 Enterprise JavaBeans Specification 2.0 的第 6、7 和 8 章中。

关于 Sun ONE 应用服务器的概述资料包含在“Sun ONE 应用服务器 Enterprise JavaBeans 技术简介”Sun ONE 应用服务器产品介绍中。



本节介绍以下主题:

关于会话 Bean 的详细信息包含在 Enterprise JavaBeans Specification 2.0 的第 6、7 和 8 章中。

关于会话 Bean


本节概述开发有效业务流程模式时需要了解的有关会话 Bean 的情况。

本节介绍以下主题:

会话 Bean 特征

会话 Bean 的定义特征必须与一个应用程序内的非持久独立状态有关。看待会话 Bean 的一种方法是将其视为 Sun ONE 应用服务器上运行的客户端应用程序的临时逻辑扩展。一般来讲,会话 Bean 不表现数据库中的共享数据,而是获得数据快照。但是,会话 Bean 可以更新数据。

会话 Bean 具有以下特征:

标准分布式应用程序的许多部分都包含逻辑代码单元,它们执行重复的、受时间限制的以及与用户相关的任务。这些任务可以是简单任务,也可以是复杂任务,通常需要在不同应用程序中使用。银行应用程序在办理任何业务之前,必须验证用户的帐户 ID 并进行结余。这样的不连续任务,实际上非常短暂,都是会话 Bean 的候选者。

示例方案

许多基于 Web 的在线购物应用程序使用的购物车是会话 Bean 的典型用途。只有在用户选定商品时,网上购物应用程序才创建 会话 Bean。完成选择时,计算购物车中的商品价格、下订单以及释放购物车对象。用户可以按在线目录继续浏览商品,而且如果用户决定下另一份订单,就创建一个新购物车。

通常情况下,会话 Bean 与其他应用程序对象不相关或没有连接。例如,购物车 Bean 可能有一个存储商品信息的数据列表成员、目前在购物车中存储的商品总成本的数据成员,以及添加、减去、包含合计商品的方法。另一方面,购物车可能与数据库根本没有活动连接。 

容器

与实体 Bean 一样,会话 Bean 可以通过 JDBC 调用访问数据库。会话 Bean 也可以提供事务处理设置。这些事务处理设置以及 JDBC 调用由会话 Bean 的容器引用,因而会话 Bean 可以参加容器管理的事务处理。

管理无状态会话 Bean 的容器具有与管理有状态会话 Bean 所不同的特权。

无状态容器

无状态容器管理无状态会话 Bean。根据定义,无状态会话 Bean 不带有针对客户端的状态。因此,就同等对待具有某种类型的所有会话 Bean。

无状态会话 Bean 容器使用 Bean 池为请求提供服务。Sun ONE 应用服务器特有的 XML 文件包含定义 Bean 池的属性:

这些属性是针对“sun-ejb-jar.xml 文件中的元素”中的部署描述符定义的。 

有状态容器

有状态容器管理有状态会话 Bean。从定义上讲,有状态会话 Bean 带有针对客户端的状态。客户端与有状态会话 Bean 之间存在一对一的关系。创建时,赋予每个有状态会话 Bean 一个唯一会话 ID,该会话 ID 可用于访问会话 Bean,这样,有状态的会话 Bean 的实例就仅由单个客户端访问。

有状态会话 Bean 是使用缓存管理的。有状态会话  Bean 缓存的大小和行为可通过指定以下参数进行控制:

max-cache-size 元素指定缓存中容纳的会话 Bean 的最大数目。如果缓存溢出(当 Bean 的数目超过 max-cache-size 时),容器就会钝化一些 Bean,或者把 Bean 的序列化状态写出到一个文件中。可以使用配置 API 从 server.xml 中获得创建该文件的目录。

这些属性是用部署描述符定义的。有关详细信息,请参阅“sun-ejb-jar.xml 文件中的元素”

钝化 Bean 存在文件系统上。server.xml 文件中的 server 元素内的 session-store 属性允许管理员指定存储钝化 Bean 的位置。默认情况下,钝化的有状态会话 Bean 存储在 instance_dir/session-store 下创建的针对应用程序的子目录中。

开发会话 Bean


当客户端完成会话 Bean 时,就释放该客户端。设计一个应用程序时,您应把每个临时、单个客户端对象指定为潜在会话 Bean。 

以下几节讨论如何开发有效会话 Bean:

开发要求

开发会话 Bean 时,您必须提供以下各项:

会话 Bean 实施类的要求:

确定会话 Bean 使用

本节提供确定实施有状态还是无状态会话 Bean 的一些准则。

有状态会话 Bean 注意事项

如果符合以下条件,以下有状态会话 Bean 适用:

由于有状态会话 Bean 对于客户端专用,随着访问应用程序的用户数目的增加,有状态会话 Bean 对于服务器资源的需要也会增加。Bean 保留在容器中,直到被客户端明确删除,或在超时时由容器删除。

容器需要将有状态会话 Bean 钝化为次要存储,因为其缓存一充满,缓存中的 Bean 超时。如果客户端随后访问 Bean,容器就负责激活 Bean。此钝化/激活过程会对服务器造成额外开销。

无状态会话 Bean 注意事项

如果具备以下任何条件,您就可能选择有状态会话 Bean:

使用无状态会话 Bean 访问数据或执行事务处理操作。无状态会话 Bean 具有极高的可扩展性,因为无状态 Bean 池中的容器管理的少数此类 Bean 有助于为大量客户端提供服务。这是可能做到的,因为无状态 Bean 与客户端没有关联。如果接收到无状态会话 Bean 的服务的请求,容器就可以自由地把请求发送到池中的任何 Bean 实例。

提供接口

作为开发者,您将负责为 Bean 提供接口。如果为 Bean 实施远程视图,则请提供一个远程组件接口和一个远程home接口。如果实施本地视图,则请提供一个本地组件接口和一个本地home接口。

要安全地使用接口,您需要认真考虑潜在部署方案,然后决定哪些接口可以是本地接口,而哪些接口可以是远程接口,最后,头脑里装着这些选择,开发应用程序代码。

以下几节讨论创建接口:

创建远程接口

会话 Bean 的远程接口定义一个用户对某个 Bean 的方法的访问。所有远程接口都扩展 javax.ejb.EJBObject。例如:

   import javax.ejb.*;
   import java.rmi.*;
   public interface MySession extends EJBObject {
   // define business method methods here....
   public String getACcountname() throws RemoteException;
   }

远程接口定义会话 Bean 的业务方法,该业务方法由某个客户调用。对于您在远程接口中定义的每种方法,您必须在 Bean 类本身中提供一个相应的方法。Bean 类中的相应方法必须具有同样的签名、同样的参数类型和返回类型。方法的名称前面附加了 ejb。例如,MySession 的实施类包含方法:

   String ejbgetAccountname() throws RemoteException
   {
   method implementation
   }

创建本地接口

开发期间可以为某个 Bean 定义本地接口,这样如果调用者处于同一容器中(即在同一地址空间或 Java 虚拟机 [JVM] 中运行),就可以以简化方式调用该 Bean。这可提高计划共处的应用程序的性能。

但是,本地接口的调用语义不同于远程接口的调用语义。例如,远程接口使用 pass-by-value 传递参数,而本地接口则使用 pass-by-reference。作为开发者,您必须识别通过本地接口传递的潜在对象共享。尤其是,注意不要把一个 Enterprise Bean 的状态指定到另一个 Enterprise Bean 的状态。您还必须小心确定通过本地接口传递的对象,尤其是在事务或安全内容发生更改的情况下。

The local interface extends the javax.ejb.EJBLocalObject interface, and is allowed to have super interfaces. The throws clause of a method defined in the local interface must not include java.rmi.RemoteException. For example:

   import javax.ejb.*;
      public interface MyLocalSession extends EJBLocalObject {
   // define business method methods here....
   }

对于本地接口中定义的每个方法,会话 Bean 的类中必须有一个匹配方法。匹配方法必须具有同一名称、同样的参数数目和类型以及同一返回类型。必须在本地接口的方法 throws 子句中定义会话 Bean 类匹配方法的 throws 子句中定义的所有异常。方法不应丢弃 java.rmi.RemoteException

创建本地home接口

home接口定义使一个使用应用程序的客户能够创建和删除会话 Bean 的方法。Enterprise Bean 的本地home接口定义是本地客户端可以创建、查找和删除 EJB 对象的方法,而且定义不是某个 Bean 实例所特有的主业务方法(会话 Bean 没有查看器和主业务方法)。 本地home接口是由您定义的,并由容器进行实施。客户端使用 JNDI 查找会话 Bean 的home接口。

本地home接口使本地客户端可以:

本地home接口始终扩展 javax.ejb.EJBLocalHome。例如:

   import javax.ejb.*;
   import java.rmi.*;

   public interface MySessionLocalBeanHome extends EJBLocalHome {
      MySessionLocalBean create() throws CreateException;
   }

create 方法

如此示例所示,一个会话 Bean 的home接口定义一个或多个 create 方法。必须把每个方法命名为 create,而且每个方法在数目参数类型方面必须与会话 Bean 类中定义的 ejbCreate 方法相对应。但是,每个 create 方法的返回类型不匹配其对应的 ejbCreate 方法的返回类型。相反,每个 create 方法必须返回该会话 Bean 的本地接口类型。

ejbCreate 方法的 throws 子句中定义的所有异常都必须在远程接口中匹配 create 方法的 throws 子句中进行定义。另外,home接口中的 throws 子句必须始终包括 javax.ejb.CreateException

Remove 方法

远程客户端可以使用 javax.ejb.EJBObject 接口上的 remove 方法或 javax.ejb.EJBHome 接口的 remove(Handle handle) 方法删除一个会话对象。

由于会话对象不具有可以访问客户端的主键,因而调用某个会话上的 javax.ejb.EBJHome.remove(Object primaryKey) 方法就会产生 javax.ejbRemoveException

创建远程home接口

容器针对定义容器中部署的远程home接口的每个会话 Bean 实施远程home接口。实施此接口的对象称为会话 EJBHome 对象。远程home接口使客户端可以执行以下操作:

远程home接口必须扩展 javax.ejb.EJBHome 接口,而且可以拥有超级接口。接口中定义的方法必须遵循 RMI/IOP 的规则。

远程home接口必须定义一个或多个 create<METHOD>(...) 方法。

远程home接口始终扩展 javax.ejb.EJBHome。例如:

   import javax.ejb.*;
   import java.rmi.*;

   public interface MySessionHome extends EJBHome {
      MySession create() throws CreateException, RemoteException;
   }

如此示例所示,一个会话 Bean 的home接口定义一个或多个 create 方法。但是,每个 create 方法的返回类型不匹配其对应的 ejbCreate 方法的返回类型。相反,每个 create 方法必须返回该会话 Bean 的本地接口类型。

ejbCreate 方法的 throws 子句中定义的所有异常都必须在远程接口中匹配 create 方法的 throws 子句中进行定义。另外,home接口中的 throws 子句必须始终包括 javax.ejb.CreateException。另外,home接口中的 throws 子句必须始终包括 javax.ejb.CreateExceptionjava.rmi.RemoteException



注意

对于无状态会话 Bean,home接口必须恰好具有一个 create 方法,而 Bean 必须恰好具有一个 ejbCreate 方法。两个方法都不接受任何参数。



创建 Bean 类定义

对于一个会话 Bean,必须把 Bean 类定义为 public,不得定义为 final,而且不能定义为 abstract。Bean 类必须实施 javax.ejb.SessionBean 接口。

import java.rmi.*;
import java.util.*;
import javax.ejb.*;
public class MySessionBean implements SessionBean {
   // Session Bean implementation. These methods must always     included.
   public void ejbActivate() {
   }
   public void ejbPassivate() {
   }
   public void ejbRemove() {
   }
   public void setSessionContext(SessionContext ctx) {
   }
   
   // other code omitted here....
   }

会话 Bean 必须实施一个或多个 ejbCreate(...) 方法。客户端调用 Bean 的每种方式都必须有一个方法。例如:

   public void ejbCreate() {         
      string[] userinfo = {"User Name", "Encrypted Password"} ;
   }

每个 ejbCreate(...) 方法必须声明为 public,返回 void,以及命名为 ejbCreate。参数必须是合法 Java RMI 类型。throws 子句可以定义应用程序特有的异常和 java.ejb.CreateException

会话 Bean 还实施一个或多个业务方法。这些方法通常是每个 Bean 所特有的,并且表示其特定功能。例如,如果一个会话 Bean 管理用户登录,它就可能包括一个称为 validateLogin 的功能。

业务方法名称可以是任何事情,但不能与 EJB 接口中的方法名称相冲突。必须把业务方法声明为 public。方法参数和返回值类型必须是合法 Java RMI 类型。throws 子句可以定义应用程序特有的异常。

会话同步

有状态会话 Bean 类定义(尤其是 javax.ejb.SessionSynchronization)中允许进行一种接口实施,此有状态会话 Bean 类定义能够向会话 Bean 实例通知事务边界,并能够将其状态与那些事务进行同步。

javax.ejb.SessionSynchronization 接口使一个有状态会话 Bean 实例可以得到其事务边界容器的通知。实施此接口时,会话 Bean 类是可选的。只有在您想要将其状态与事务同步时,会话 Bean 才应实施此接口。例如,在新的事务开始后、但在事务提交之前和提交之后,实施此接口的有状态会话 Bean 将获得回叫。

有关此接口的详细信息,请参阅 Enterprise JavaBeans Specification 2.0。



注意

容器将只调用使用容器管理事务的有状态会话 Bean 的会话同步接口方法。



抽象方法

除了您在远程接口中定义的业务方法之外,EJBObject 接口定义使您能够执行以下操作的多个抽象方法:

有关这些内置方法以及如何使用的详细信息,请参阅 Enterprise JavaBeans Specification v2.0。

容器提供的部署工具负责在部署会话时生成更多子句。

限制和优化


本节讨论对于开发会话 Bean 的限制,并提供一些优化准则:

优化会话 Bean 性能

对于有状态会话 Bean,使有状态 Bean 与其客户端共存,这样客户端和 Bean 就在同一过程地址空间执行,从而会提高性能。

限制事务

以下对事务的限制由容器执行,并且开发会话 Bean 中必须遵守:


上一部分 | 目录 | 索引 | 下一部分
Copyright 2002 Sun Microsystems, Inc. All rights reserved.