与无状态会话Bean类似,有状态会话Bean也包含Bean类及业务接口。
Bean类
一个有状态会话Bean类是带有@Stateful注释符的标准Java类,如果使用了部署描述符而不是注释符,那么Bean类应被标为一个有状态会话Bean。在混合模式的情况中,同时有注释符及部署描述符,且在类中使用了类级别或成员级别的注释符,那么也必须指定@Stateful注释符。
为演示有状态会话Bean,我们将创建一个ShoppingCart会话Bean,其保持追踪添加到用户“购物车”中的商品及各自的数量,在本文中,将使用硬编码演示客户端与有状态会话Bean之间的状态及会话维护。例9中为一个ShoppingCart会话Bean的定义。
例9:ShoppingCartBean.java package com.apress.ejb3.chapter02; import javax.ejb.Stateful; @Stateful(name="ShoppingCart") public class ShoppingCartBean implements ShoppingCart, ShoppingCartLocal { public ShoppingCartBean() { } }
在这个例子中,交易发生之前及之后,应用程序想要通过EJB容器获取相应通知,并使用这些通知来管理相关数据。有状态会话Bean在实现了javax.ejb.SessionSynchronization接口后,可通过EJB容器接收这种通知,但这是一个可选项。有状态会话Bean可从EJB容器中接收以下三种类型的交易通知:
afterBegin:表明一个新的交易开始。
beforeCompletion:表明交易即将提交。
afterCompletion:表明交易已经完成。
例如,ShoppingCart会话Bean将实现javax.ejb.SessionSynchronization接口以得到一个afterCompletion通知,所以,它可以清空“购物车”缓存。
业务接口
有状态会话Bean的业务接口与无状态会话Bean中的类似,且使用相同的注释符:@Local和 @Remote。ShoppingCart会话Bean有远程及本地两种接口,如图6所示:
图6:ShoppingCart中的业务接口
在我们的Web程序中,将主要用到本地接口,而远程接口在此主要是便于Bean的单元测试。
例10与例11 为ShoppingCart的远程及本地业务接口,它们各自带有@Remote与@Local注释符。
例10:ShoppingCart.java package com.apress.ejb3.chapter02; import javax.ejb.Remote; @Remote public interface ShoppingCart { }
例11:ShoppingCartLocal.java package com.apress.ejb3.chapter02; import javax.ejb.Local; @Local public interface ShoppingCartLocal { }
在此,大家也可按例12中的编码风格,在通过业务接口名指定@Stateful或@Stateless之前,先指定@Local与@Remote注释符。
例12:ShoppingCartBean.java package com.apress.ejb3.chapter02; import javax.ejb.Local; import javax.ejb.Remote; import javax.ejb.Stateful; @Local({ShoppingCartLocal.class}) @Remote({ShoppingCart.class}) @Stateful(name="ShoppingCart") public class ShoppingCartBean implements ShoppingCart, ShoppingCartLocal { public ShoppingCartBean() { } }