有状态会话bean

在会话bean综述中,描述了无状态和有状态bean的区别在于客户端和服务器之间交互形式不同。对于无状态会话bean,交互的开始和结束都在同一个方法中。有时客户端需要发出多个服务请求(需要调用多个方法),而每个请求需要访问或者考虑前面的请求结果。有状态会话bean的出现就是为了处理这种情况,通过向客户端提供一个专用的服务(某一个可以保留前面状态的bean),当客户端获得bean的引用时启动该服务,并且只有当客户端选择结束会话时才结束。回到饭店吃饭的例子就是当你点餐的时候一个服务员在为你服务,直到你离开饭店这个服务员才会被释放,吃饭过程中全部是同一个人在为你服务。

说到有状态会话bean,不得不提的一个例子就是购物车的例子,这是一个典型的有状态会话bean的例子。客户端获取购物车的引用,启动会话。在用户会话期间,客户端在购物车中添加或删除项目,其中购物车维护特定于客户端的状态。然后,当会话结束时,客户端完成购买,购物车才会被删除。

这与在普通的Java应用程序代码中使用一个非委托的java对象没什么不同。我们创建了一个类的实例,调用对象上的操作(set方法)改变实例中的属性值,然后当不再需要对象时释放它。有状态会话bean与上面提到的普通Java对象的区别是服务器管理实际的对象实例,而客户端与该实例通过bean的业务接口进行间接地交互。注意这里客户端知道的仅仅是一个接口,而不是像普通Java应用程序中那样拿到这个实例的真正引用。

有状态会话bean提供了无状态会话bean可用功能的一个超集。无状态会话bean所包含的功能,如远程接口功能,同样也适用于有状态会话bean。

1.定义有状态会话bean

以典型的购物车的例子作为代表定义有状态会话bean,类似于无状态会话bean,有状态会话bean是由一个或多个有单一的bean类实现的业务接口组成。购物车bean的一个本地业务接口示例如下代码所示

public interface ShoppingCart {
    public void addItem(String id, int quantity);
    public void removeItem(String id, int quantity);
    public Map<String, Integer> getItems();
    public void checkout(int paymentId);
    public void cancel();
}

下面代码显示了实现ShoppingCart接口的bean类。通过@Stateful注解标记这个bean类,来告诉服务器该类是一个有状态会话bean。

@Stateful
public class ShoppingCartBean implements ShoppingCart {
    private HashMap<String,Integer> items = new HashMap<String,Integer>();

    public void addItem(String item, int quantity) {
        Integer orderQuantity = items.get(item);
        if (orderQuantity == null) {
            orderQuantity = 0;
        }
        orderQuantity += quantity;
        items.put(item, orderQuantity);
    }

    public void removeItem(String item, int quantity) {
        Integer orderQuantity = items.get(item);
        if (orderQuantity == null) {
            return;
        }
        orderQuantity -= quantity;
        if (orderQuantity > 0) {
            items.put(item, orderQuantity);
        } else {
            items.remove(item);
        }
    }

    public Map<String, Integer> getItems() {
        return items;
    }

    @Remove
    public void checkout(int paymentId) {
        // store items to database
        // ...
    }

    @Remove
    public void cancel() {
    }
}

写完接口与实现之后来比较一下无状态会话bean与有状态会话bean,主要存在下面两方面的不同。

第一个区别是该bean类具有类似于普通Java类中属性的状态字段(这里指item),可以通过bean的业务方法对其进行修改。因为使用该bean的客户端可以有效的访问一个私有会话bean实例,并对其进行更改,注意这里的访问不是指客户端直接拿到某个bean的实例,而是通过业务接口对其进行操作。

第二个区别是拥有使用@Remove注解标记的方法。客户端将使用这些方法来结束与bean的会话。调用了一个这样的方法之后,服务器将销毁bean实例。如果后续尝试继续调用业务方法,那么客户端引用将会抛出异常(这与无状态会话bean不同,无状态会话bean更自由一些,拿来就用用完拉倒。这也是业界更倾向于不使用有状态会话bean的主要原因之一)。每个有状态会话bean必须至少定义一个使用@Remove注解标记的方法,即使该方法除了结束会话之外不做其他事情。在代码中如果用户完成了商店交易,就调用checkout()方法;相反,如果用户决定不继续交易就调用cancel()方法。两种情况都将会删除会话bean

2.生命周期回调

和无状态会话bean一样,有状态会话bean也支持生命周期的回调,以便于bean的初始化和清理。它还支持两个额外的回调,以允许bean有效地处理bean实例的钝化(passivation)和激活(activation)进程。钝化是由服务器序列化bean实例的进程,使得可以对它进行脱机存储以释放资源或者复制到集群中的另一个服务器上。激活处理则反序列化一个钝化的会话bean实例,使之在服务器上再次变得活动。因为有状态会话bean保留代表客户端的状态,并且直至调用bean的一个remove方法之后才会删除,所以,服务器不能销毁一个bean实例以释放资源。钝化允许在服务器保留会话状态的同时回收资源。

在钝化之前,服务器将调用Prepassivate回调。Bean使用此回调为bean的序列化做准备,通常关闭任何只想其他服务器资源的活动连接。PrePassivate方法由@prePassivate标记注解所标识。在已经激活bean之后,服务器将调用PostActivate回调。锁着序列化实例的恢复,bean必须重新获取bean的业务方法可能依赖的任何其他资源的连接。PostActivate方法由@PostActivate标记注解所标识。代码中显示了会话bean充分利用回调声明周期来维护一个JDBC连接。注意,只有JDBC连接是显式地管理。作为资源连接工厂,服务器在钝化和激活期间会自动保存和恢复数据源。

@Stateful
// WARMING:
// Resource declaration is covered later in the chapter.
// use of mappedName is vendor specific.  In this case, it is used
// to specify the JNDI location of the datasource to use.
@Resource(name="jdbc/ds", type=DataSource.class, mappedName="jdbc/sfsbLifecycleExample")
public class OrderBrowserBean implements OrderBrowser {
    DataSource ds;
    Connection conn;

    @PostConstruct
    public void init() {
        // acquire the data source
        try {
            ds = (DataSource)
                new InitialContext().lookup("java:comp/env/jdbc/ds");
        } catch (Exception e) {
            throw new EJBException(e);
        }
        acquireConnection();
    }

    @PrePassivate
    public void passivate() {
        releaseConnection();
    }

    @PostActivate
    public void activate() {
        acquireConnection();
    }

    @PreDestroy
    public void shutdown() {
        releaseConnection();
    }

    private void acquireConnection() {
        try {
            conn = ds.getConnection();
        } catch (SQLException e) {
            throw new EJBException(e);
        }
    }

    private void releaseConnection() {
        try {
            conn.close();
        } catch (SQLException e) {
        }
        conn = null;
    }

    public Collection<Order> listOrders() {
        // ...
        return new ArrayList<Order>();
    }
}
时间: 2024-10-13 09:52:31

有状态会话bean的相关文章

无状态会话bean(1)---定义

无状态会话bean用于完毕在单个方法的生命周期内的操作.无状态bean能够实现很多业务操作,可是每一个方法都不能假定不论什么其它的方法会在它之前调用.后半句的意思是如今的你可能不是刚才的你.明天的你可也能不是今天的你,这个时候你就叫做"无状态你". 上面的阐述听起来像是无状态的bean的一个局限,好像每次再见就像永别似的. 可是这是迄今为止业务服务最常见的形式,就像去饭店吃饭,点菜的服务员与给你上菜的服务员是不是同一个这不是我们所关心的. 无状态回话bean不同于适合在对话中积累状态(

无状态会话bean(1)---定义(未排版)

无状态会话bean用于完成在单个方法的生命周期内的操作.无状态bean可以实现许多业务操作,但是每个方法都不能假定任何其他的方法会在它之前调用. 这听起来像是无状态的bean的一个局限.但是这是迄今为止业务服务最常见的形式.不同于适合在对话中积累状态(如零售应用程序的购物车)的有状态会话bean,无状态回话bean旨在非常有效的执行独立操作.无状态会话bean可以在最小化对整体服务器资源影响的同时,扩展到大量的客户端. 会话bean定义分为如下两个部分: 零个或多个业务接口,定义了一个客户端在b

无状态会话bean(2)----声明周期回调(未排版)

与用于应用程序代码的常规Java类不同,服务器管理无状态会话bean的声明周期它在两个方面影响了一个bean的实现. 首先,服务器决定了创建和删除bean实例的时间.应用程序不会控制何时或者甚至创建多少特定的无状态会话bean实例,或者它们将存活多久. 第二,服务器必须在构建之后,但是在调用bean的业务逻辑之前,初始化bean服务.同样,该bean可能必须在使用业务方法之前获得可用的资源,如JDBC数据源.然而,为了使得bean获取资源,服务器必须首先完成初始化bean服务.这限制了类的构造函

Ejb in action(四)——购物车实例演示有状态会话Bean

前面.我们介绍了一个入门实例.事实上那就是无状态回话Bean的经常使用情况. 上一篇文章中.我们介绍了无状态会话Bean和有状态会话Bean的相关概念.为了加深大家对它们的理解,我们一起来实现一个有状态会话Bean的样例--模拟购物车. 这个样例很经典:一个client购物的过程中.服务端会创建一个SessionBean保存着这一client的状态.client买的东西,都会在服务端进行存储. 也就是说.自始至终,一直存在一个有状态会话Bean对象.与该client进行交互. 以下来看详细实现:

EJB开发第一个无状态会话bean、开发EJB客户端

开发第一个无状态会话bean EJB中的三中bean: 会话Bean(Session Bean) 负责与客户端交互,是编写业务逻辑的地方,在会话bean中可以通过JDBC直接操作数据库,但大多数情况下都是通过实体bean来完成对数据库的操作. 实体Bean(Entity Bean) 它实际上属于java持久化规范(JPA)里的技术,JPA的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结束现在Hibernate.TopLink等ORM框架各自为营的局面. 消息驱动Bean(Messag

JBoss+Ant实现EJB无状态会话bean实例

EJB分为session bean.entity bean.message-driven bean,session bean又分为无状态会话bean和有状态会话bean. session bean负责与客户端交互,是编写业务逻辑的地方,在session bean中可以通过jdbc直接操作数据库,但大多数情况下都是通过entity bean来完成对数据库的操作的. 平常,我们使用最多的是无状态bean,因为它的bean实例可供多个用户使用,所以它的性能比有状态bean高.正因为一个bean实例被多

无状态会话bean(3)---远程业务接口(未排版)

迄今为止,我们只讨论了使用一个本地业务接口的会话bean.在这种情况下,本地意味着只能由运行在同一个应用程序服务器实例的JavaEE组件声明会话bean的依赖性.例如,远程客户端不可能通过本地接口使用会话bean. 为了容纳远程客户端,会话bean可以采用@Remote注解来标记它们的业务接口,以声明它是远程可用的.下面代码演示了前面所示的HelloService接口的远程版本语法.标记一个接口为远程的相当于使其扩展java.rmi.Remote接口.客户端获取的bean的引用不再是服务器上的一

会话bean综述(未排版)

会话bean就像上篇文章中提到的它的目的是提供一种旨在封装业务服务的组件技术.通常使用常规的Java接口来定义该服务支持的操作,把它作为会话bean的业务接口,客户端通过它与bean进行交互.平时做开发的时候好像没有定义过接口,而是直接将会话bean拿过来用.实现会话bean比常规的Java类略微复杂一点,如果存在一个业务接口,那么它将会实现这个接口.然而由于是EJB组件模型的一部分,因此该bean可以访问一些列广泛容器服务以实现业务服务.名称"会话bean"的意义在于客户端访问它们以

3、EJB3.0开发第一个无会话Bean和客户端(jboss4.2.3)

1.EJB中的3种bean 1.会话bean 负责与客户端交互,在编写业务逻辑的地方,会话bean可以通过jdbc直接操作数据库 分为: 无状态会话bean:我们使用最多的是无状态会话bean,因为它的bean实例可以被多个用户使用,性能比有状态会话bean高,但是无法保存某个用户设置的值 有状态会话bean:它的一个bean实例只供一个用户使用,所以它的性能开销比较大 2.实体bean 属性java持久化规范(JPA)里的技术,JPA的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结