EJB会话bean购物车实例教程.docx

上传人:b****6 文档编号:7950053 上传时间:2023-01-27 格式:DOCX 页数:12 大小:51.07KB
下载 相关 举报
EJB会话bean购物车实例教程.docx_第1页
第1页 / 共12页
EJB会话bean购物车实例教程.docx_第2页
第2页 / 共12页
EJB会话bean购物车实例教程.docx_第3页
第3页 / 共12页
EJB会话bean购物车实例教程.docx_第4页
第4页 / 共12页
EJB会话bean购物车实例教程.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

EJB会话bean购物车实例教程.docx

《EJB会话bean购物车实例教程.docx》由会员分享,可在线阅读,更多相关《EJB会话bean购物车实例教程.docx(12页珍藏版)》请在冰豆网上搜索。

EJB会话bean购物车实例教程.docx

EJB会话bean购物车实例教程

EJB会话bean购物车实例教程

有状态会话Bean示例

会话Bean功能强大,因为它把客户端的区域扩展到了服务器(在服务器端保存客户端某些特定数据),然而它们仍然很容易创建。

在第二章你已经建立了一个无状态会话Bean的例子ConvertEJB。

这一章我们将创建一个购物车的有状态会话BeanCartEJB。

内容:

购物车会话BeanCartEJB

会话Bean类

Home接口

Remote接口

辅助类

运行该例子

其他企业Bean特征

访问环境实体

企业Bean的比较

传递企业Bean的对象引用

1.购物车会话BeanCartEJB

CartEJB描述一个在线书店的购物车。

它的客户端的动作可能有:

增加一本书,减少一本书,浏览购物车中存放的所有书。

要建立该企业Bean,需要以下文件:

●会话Bean类文件(CartBean.java)

●Home接口(CartHome.java)

●Remote接口(Cart.java)

所有的会话Bean都需要一个会话Bean类,所有允许远程访问的企业Bean都必须有一个Home接口和一个Remote接口(好像在哪说过了,不知道可不可以有多个:

)。

因为特定应用程序的需要,企业Bean可能也需要一些辅助类。

本例的购物车用到两个辅助类:

BookException和IdVerifier。

这两个类将在后续节里介绍。

本例的原文件在j2eetutorial/examples/src/ejb/cart目录下。

要编译这些文件进入j2eetutorial/examples目录执行如下命令:

antcart

一个CartApp.ear的样本文件可以在j2eetutorial/examples/ears目录下找到。

会话Bean类

本例的会话Bean类是CartBean类。

以CartBean为例,下面列出所有会话Bean都具有的特征:

●它们都实现SessionBean接口(呵呵,它什么也不做,只是继承了Serializable接口而已)

●会话Bean类必须声明为public

●会话Bean类不能被定义为abstract或者final(就是说它不能是抽象类,而且允许被继承)

●至少实现一个ejbCreate方法

●实现特定的商业方法

●包含一个无参数的构造函数

●不能定义finalize方法

以下是CartBean.java的代码:

importjava.util.*;

importjavax.ejb.*;

publicclassCartBeanimplements会话Bean{

StringcustomerName;

StringcustomerId;

Vectorcontents;

publicvoidejbCreate(Stringperson)

throwsCreateException{

if(person==null){

thrownewCreateException("Nullpersonnotallowed.");

}

else{

customerName=person;

}

customerId="0";

contents=newVector();

}

publicvoidejbCreate(Stringperson,Stringid)

throwsCreateException{

if(person==null){

thrownewCreateException("Nullpersonnotallowed.");

}

else{

customerName=person;

}

IdVerifieridChecker=newIdVerifier();

if(idChecker.validate(id)){

customerId=id;

}

else{

thrownewCreateException("Invalidid:

"+id);

}

contents=newVector();

}

publicvoidaddBook(Stringtitle){

contents.addElement(title);

}

publicvoidremoveBook(Stringtitle)throwsBookException{

booleanresult=contents.removeElement(title);

if(result==false){

thrownewBookException(title+"notincart.");

}

}

publicVectorgetContents(){

returncontents;

}

publicCartBean(){}

publicvoidejbRemove(){}

publicvoidejbActivate(){}

publicvoidejbPassivate(){}

publicvoidsetSessionContext(SessionContextsc){}

}

SessionBean接口

SessionBean接口继承EnterpriseBean接口,后者又继承Serializable接口。

SessionBean接口声明了ejbRemove,ejbActivate,ejbPassivate和setSessionContext方法。

虽然本例中CartBean没有用到这些方法,但也要实现它们,也为它们在SessionBean节口中声明过。

因此在CartBean中被实现为空方法。

大家可能都注意到了,该接口没有声明ejbCreate方法,该方法因为形式太自由(有状态会话Bean在实现的时候可能会有不确定个的参数,实体Bean的ejbCreate方法就更不用说了,不过可惜的是实体Bean并不实现该接口:

),所以该方法无法作为固定类型的方法在接口中声明,该方法在被EJB容器调用时也只有以方法名作为标志,这可不太符合面向对象的原则。

随后介绍什么时候使用这些方法。

ejbCreate方法

因为企业Bean运行在EJB容器中,所以客户端不可能直接创建一个企业Bean的实例,只有EJB容器有能力这么做。

下面是本例创建CartEJB实例的过程:

1.客户端调用Home对象的create方法

CartshoppingCart=home.create("DukeDeEarl","123");

2.EJB容器创建一个企业Bean(本例中是CartEJB)的实例

3.EJB容器调用企业Bean相应的ejbCreate方法,CartEJB中对应的方法:

publicvoidejbCreate(Stringperson,Stringid)

throwsCreateException{

if(person==null){

thrownewCreateException("Nullpersonnotallowed.");

}

else{

customerName=person;

}

IdVerifieridChecker=newIdVerifier();

if(idChecker.validate(id)){

customerId=id;

}

else{

thrownewCreateException("Invalidid:

"+id);

}

contents=newVector();

}

一般地,ejbCreate方法初始化企业Bean的状态。

例如上述的ejbCreate方法就通过方法参数初始化customerName和customerId两个变量。

企业Bean必须至少实现一个ejbCreate方法(这句话好像重复了很多遍了,没办法这个确实很重要嘛:

)。

该方法签名必须符合以下要求:

●方法的访问权修饰必须是public

●返回值类型必须是void

●如果该企业Bean允许远程访问,那么方法的参数必须是符合Java远程方法调用API(JavaRemoteMethodInvocation,JavaRMI)规则的合法类型,就是说必须是实现了Serializable接口或它的字接口的类的对象。

●方法不可以是static或final的

throws子句必须包含javax.ejb.CreateException异常。

EjbCreate方法遇到非法的参数也会抛出该异常。

商业方法

会话Bean的主要作用就是执行客户端要求的商业逻辑。

客户端调用Home对象的create方法返回的远程对象引用中的商业方法,在客户端透视图中,这些商业方法好像是在本地运行,实际上它们确实在远程会话Bean中运行。

下面的代码片断展示了CartClient客户端如何调用商业方法:

CartshoppingCart=home.create("DukeDeEarl","123");

...

shoppingCart.addBook("TheMartianChronicles");

shoppingCart.removeBook("AliceInWonderland");

bookList=shoppingCart.getContents();

CartBean类中商业方法的实现如下

publicvoidaddBook(Stringtitle){

contents.addElement(newString(title));

}

publicvoidremoveBook(Stringtitle)throwsBookException{

booleanresult=contents.removeElement(title);

if(result==false){

thrownewBookException(title+"notincart.");

}

}

publicVectorgetContents(){

returncontents;

}

商业方法必须遵循以下规则:

●方法名不能和EJB体系定义的方法冲突,例如不可以命名为ejbCreate或者ejbActivate

●访问权修饰符必须是public

●如果企业Bean允许远程访问,参数和返回值必须符合JavaRMIAPI调用规则

●不可以用statci和final修饰符(和ejbCreate一样)

throws子句可以包含任意类型的异常,不过要有意义。

例如removeBook方法就会在购物车中没有要删除的书是抛出BookException异常。

为了可以指出像无法连接数据库这样的系统错误,商业方法的应该在这时抛出javax.ejb.EJBException异常。

当商业方法抛出该异常,容器会将其包装到一个RemoteException异常中,后者会被客户端捕获。

容器不会擅自包装应用程序自定义异常,如本例中的BookException异常。

因为EJBException异常是RutimeException(该异常类型系统会自动处理)异常类的子类,所以你不需要把它也加入到商业方法的throws子句中。

Home接口

企业Bean的Home接口继承javax.ejb.EJBHome接口。

对于会话Bean,Home接口的目标是要定义客户端可访问create方法。

如本例的CartClient客户端:

CartshoppingCart=home.create("DukeDeEarl","123");

Home接口中的每一个create方法都对应一个企业Bean类中的ejbCreate方法。

CartBean的ejbCreate方法声明如下:

publicvoidejbCreate(Stringperson)throwsCreateException

...

publicvoidejbCreate(Stringperson,Stringid)

throwsCreateException

对比一下CartHome接口中的create方法声明:

importjava.io.Serializable;

importjava.rmi.RemoteException;

importjavax.ejb.CreateException;

importjavax.ejb.EJBHome;

publicinterfaceCartHomeextendsEJBHome{

Cartcreate(Stringperson)throws

RemoteException,CreateException;

Cartcreate(Stringperson,Stringid)throws

RemoteException,CreateException;

}

以上两个文件中的ejbCreate和create方法声明很相似,但是也有重要的不同。

下面是Home接口的create方法声明规则:

●参数个数和类型必须和对应的ejbCreate方法一样,就是说要为企业Bean的每一个ejbCreate方法(永远不会用到的除外:

)在Home接口中声明一个对应的参数个数类型和顺序一模一样的create方法

●参数和返回值类型必须符合RMI调用规则

●create方法的返回值类型是企业Bean的Remote接口类型(对应的ejbCreate方法返回void)

●throws子句中必须包含java.rmi.RemoteException和javax.ejb.CreateException异常

Remote接口

Remote接口继承EJBObject接口,它定义客户端调用的商业方法。

下面是本例中的Remote接口Cart.java的代码:

importjava.util.*;

importjavax.ejb.EJBObject;

importjava.rmi.RemoteException;

publicinterfaceCartextendsEJBObject{

publicvoidaddBook(Stringtitle)throwsRemoteException;

publicvoidremoveBook(Stringtitle)throws

BookException,RemoteException;

publicVectorgetContents()throwsRemoteException;

}

Remote接口中的方法定义规则如下:

●每一个商业方法声明必须在企业Bean类里实现有一个对应的商业方法

●必须与对应的企业Bean类实现的商业方法的声明签名一样,就是说参数类型个数顺序和返回值类型都必须一样。

●参数和返回值类型也必须符合RMI调用规则

●throws子句必须包含RemoteException异常,就是在对应的企业Bean商业方法的throws子句的基础上加一个RemoteException组成Remote接口中相应方法的throws子句。

辅助类

本例有两个辅助类:

BookException和IdVerifier。

BookException异常类在removeBook方法找不到要删除的书时被抛出。

IdVerifier在ejbCreate方法中被调用来验证custormerId的有效性。

辅助类文件必须和调用它们的企业Bean类文件打包到同一个EJBJAR文件中。

运行本例

1.启动J2EE服务器和deploytool工具

2.在deploytool工具中打开j2eetutorial/examples/ears/CartApp.ear文件,你可以在图4-1中看到本例的CartApp应用程序

3.部署CartApp应用程序(ToolsDeploy)。

在进入的对话框中确认你已经选择了ReturnClientJAR复选框

4.运行

a)在终端窗口中进入j2eetutorial/examples/ears目录

b)将环境变量APPCPATH设置为CartAppClient.jar文件的目录

c)执行如下命令:

runclient-clientCartApp.ear-nameCartClient-textauth

d)出现登录提示符后,输入用户名:

guest,密码:

guest123

图4-1CartApp应用程序的General选项面板

二其他的企业Bean特性

下面的这些特性是会话Bean和实体Bean的公有特性。

访问环境变量

在部署描述符中存储的环境变量是你不改变企业Bean的源代码也可以定制商业逻辑的名字-值对。

例如一个计算商品折扣的企业Bean,用一个环境变量DiscountPercent来存储折扣比例。

在应用程序部署前,你可以用deploytool在EnvEntries页里给DiscountPercent赋值0.05。

(如图4-2)当你运行该程序,企业Bean从它的运行环境中得到0.05的折扣比例。

Figure4-2CheckerBean的Env.Entries页

在下面的示例代码中,applyDiscount方法根据购买数量用环境变量计算折扣。

首先,它以java:

comp/env参数调用lookup方法来定位环境命名上下文对象,然后用环境上下文对象的lookup方法得到DiscountLevel和DiscountPercent环境变量的值。

这里将把0.05赋给discountPercent变量。

applyDiscount方法是CheckerBean类的方法,该类的源文件放在j2eetutorial/examples/src/ejb/checker目录下,对应的样本CheckerApp.ear文件放在j2eetutorial/examples/ears目录下。

publicdoubleapplyDiscount(doubleamount){

try{

doublediscount;

Contextinitial=newInitialContext();

Contextenvironment=

(Context)initial.lookup("java:

comp/env");

DoublediscountLevel=

(Double)environment.lookup("DiscountLevel");

DoublediscountPercent=

(Double)environment.lookup("DiscountPercent");

if(amount>=discountLevel.doubleValue()){

discount=discountPercent.doubleValue();

}

else{

discount=0.00;

}

returnamount*(1.00-discount);

}catch(NamingExceptionex){

thrownewEJBException("NamingException:

"+

ex.getMessage());

}

}

企业Bean的比较

客户端可以调用isIdentical方法来判断两个有状态会话Bean是否等价:

bookCart=home.create("BillShakespeare");

videoCart=home.create("LeftyLee");

...

if(bookCart.isIdentical(bookCart)){

//true...}

if(bookCart.isIdentical(videoCart)){

//false...}

因为无状态会话Bean的对象都是等价的,所以用isIdentical方法比较他们时总是返回真。

实体Bean的等价判断也可以用isIdentical方法,不过这里还有另外一种方法,就是比较它们的主键:

Stringkey1=(String)accta.getPrimaryKey();

Stringkey2=(String)acctb.getPrimaryKey();

if(pareTo(key2)==0)

System.out.println("equal");

访问企业Bean的远程对象引用

有时你的企业Bean需要提供一个自己的引用给其他企业Bean。

例如你可以通过引用使企业Bean可以调用另一个企业Bean的方法。

你无法访问this引用因为它指向在EJB容器中运行的Bean实例,只有容器可以直接调用Bean实例的方法。

客户端通过远程接口实现对象间接调用Bean的方法,通过这些对象(远程接口实现对象)的引用企业Bean可以互相访问。

会话Bean调用SessionContext接口定义的getEJBObject方法获得它的远程接口对象引用。

而实体Bean调用的是EntityContext接口定义的getEJBObject方法。

这两个借口提供企业Bean访问EJB容器管理的上下文对象。

典型情况下,企业Bean通过setSessionContext方法保存它的上下文对象。

下面的代码片断说明了会话Bean如何使用这些方法:

publicclassWagonBeanimplementsSessionBean{

SessionContextcontext;

...

publicvoidsetSessionContext(SessionContextsc){

this.context=sc;

}

...

publicvoidpassItOn(Basketbasket){

...

basket.copyItems(context.getEJBObject());

}

...

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 考试认证 > 财会金融考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1