用 WSAD5.0和SQLServer2K采用Meet-in-Middle模式开发CMP实体Bean及其完整客户端(下篇:客户端的开发和性能优化)

用 WSAD5.0和SQLServer2K采用Meet-in-Middle模式开发
CMP实体Bean及其完整客户端
(下篇:客户端的开发和性能优化)

abnerchai( 柴政 ) 2004 年 6 月

接上篇:

14 、下面我们编写一个 SessionBean 来测试我们的 CMP 实体 Bean 。我们的通常做法是用 SessionBean 来封装 CMP 实体 Bean ,然后再在 JavaBean 和 Servlets 及 jsp 中引用该 SessionBean 。这样使得 CMP 实体 Bean 对用户来说是不可见的。创建 SessionBean 的过程如下:

首先,接着上面的步骤,在 j2ee 视图中的 ejbModule 下建一个包,并命名为: com.employee.session

然后,再在此包上点右键 -> 新建 -> 其它如下图所示:

然后在弹出的框中选择 EJB-> 企业 Bean ,如下图所示,并选择“下一步”

进入如下图所示,选择好后,单击“下一步”

进入如下图所示画面:

在上图中,选择“会话 bean ”,并在 Bean 名中,输入: EmployeeSession ,并把缺省包选择为: com.employee.session, 然后点击下一步。进入如下图所示:

这里无须变动,直接点击“完成”。

这样,便创建了一个 StateLess SessionBean ,它包括三个文件:

Remote 接口: EmployeeSession.java

Home 接口: EmployeeSessionHome.java

Bean 本身: EmployeeSessionBean.java

•  下面我们来修改 SessionBean ,使之对 CMP 实体 BEAN 进行包装。

在 j2ee 视图中,双击 com.employee.session 包下面的 EmployeeSessionBean.java 文件,打开它编辑,在类中增加方法,增加后的 EmployeeSessionBean.java 文件内容如下所示:

package com.employee.session;

import java.rmi.RemoteException;

import java.util.Collection;

import java.util.Iterator;

import java.util.Vector;

import javax.ejb.CreateException;

import javax.ejb.FinderException;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.rmi.PortableRemoteObject;

import com.employee.com.Employee;

import com.employee.com.EmployeeHome;

import com.employee.com.EmployeeKey;

/**

* Bean implementation class for Enterprise Bean: EmployeeSession

*/

public class EmployeeSessionBean implements javax.ejb.SessionBean {

private javax.ejb.SessionContext mySessionCtx;

/**

* getSessionContext

*/

public javax.ejb.SessionContext getSessionContext() {

return mySessionCtx;

}

/**

* setSessionContext

*/

public void setSessionContext(javax.ejb.SessionContext ctx) {

mySessionCtx = ctx;

}

/**

* ejbCreate

*/

public void ejbCreate() throws javax.ejb.CreateException {

}

/**

* ejbActivate

*/

public void ejbActivate() {

}

/**

* ejbPassivate

*/

public void ejbPassivate() {

}

/**

* ejbRemove

*/

public void ejbRemove() {

}

/**

* 私有方法,获得实体Bean的Home接口

* @return 返回实体Bean的Home接口对象

*/

private EmployeeHome getEmployeeHome(){

InitialContext initialContext = null ;

EmployeeHome employeeHome = null ;

try {

initialContext = new InitialContext();

Object employeeHomeObject = initialContext.lookup( "ejb/com/employee/com/EmployeeHome" );

employeeHome = (EmployeeHome)PortableRemoteObject.narrow(employeeHomeObject,EmployeeHome. class );

} catch (NamingException e){

System.err.println( "CaughtException:" +e.toString());

employeeHome = null ;

e.printStackTrace();

} finally {

if (initialContext!= null )

try {

initialContext.close();

} catch (NamingException e) {

}

}

return employeeHome;

}

/**

* 私有方法:获得一个对应ID的实体Bean实体对象,如果没有找到,则用

* 给定的ID创建一个实体Bean对象

* @param id:给定要查找的对象的id

* @return 返回给定ID的一个对应的实体对象

*/

private Employee getEmployee( int id){

Employee employee = null ;

EmployeeHome employeeHome = this .getEmployeeHome();

try {

try {

if (employeeHome!= null ){

employee = employeeHome.findByPrimaryKey( new EmployeeKey(id));

}

} catch (FinderException e) {

System.out.println( "Can not find a Employee with gived id,So try to create one." );

employee = employeeHome.create(id, null , null );

}

} catch (Exception e) {

System.err.println( "CaughtException:" +e.toString());

employee = null ;

e.printStackTrace();

} finally {

employeeHome = null ;

}

return employee;

}

/**

* 远程方法:用给定的信息生成一个实体Bean对象记录。

* @param id:给定需要创建对象的id

* @param name:给定要创建对象的name

* @param email:给定要创建对象的email

* @return 返回成功创建对象的id

*/

public int createOneEmployee( int id,String name,String email){

EmployeeHome employeeHome = this .getEmployeeHome();

try {

if (employeeHome!= null ){

employeeHome.create(id,name,email);

}

} catch (RemoteException e) {

System.err.println( "CaughtException:" +e.toString());

e.printStackTrace();

} catch (CreateException e) {

System.err.println( "CaughtException:" +e.toString());

e.printStackTrace();

} finally {

employeeHome = null ;

}

return id;

}

/**

* 远程方法:返回给定id对应对象的name

* @param id:给定的id

* @return 返回对应id对象的name字符串

*/

public String getNameById( int id){

String name = null ;

Employee employee = null ;

employee = this .getEmployee(id);

if (employee!= null ) try {

name = employee.getName();

} catch (RemoteException e) {

System.err.println( "Can not get Name by given id!" );

employee = null ;

e.printStackTrace();

}

return name;

}

/**

* 远程方法:返回给定id对应对象的email

* @param id:给定的id

* @return 返回对应id对象的email字符串

*/

public String getEmailById( int id){

String email = null ;

Employee employee = null ;

employee = this .getEmployee(id);

if (employee!= null ) try {

email = employee.getEmail();

} catch (RemoteException e) {

System.err.println( "Can not get Email by given id!" );

employee = null ;

e.printStackTrace();

}

return email;

}

/**

* 远程方法:给定一个id和name,将该id对应的name设定为给定的name

* @param id:给定的id

* @param name,新的name

* @return 返回设定对象的id

*

*/

public int setNameById( int id,String name){

Employee employee = null ;

employee = this .getEmployee(id);

try {

employee.setName(name);

} catch (RemoteException e) {

System.err.println( "Can not set name by given id!" );

employee = null ;

e.printStackTrace();

}

return id;

}

/**

* 远程方法:给定一个id和email,将该id对应的email设定为给定的email

* @param id:给定的id

* @param name,新的email

* @return 返回设定对象的id

*

*/

public int setEmailById( int id,String email){

Employee employee = null ;

employee = this .getEmployee(id);

try {

employee.setEmail(email);

} catch (RemoteException e) {

System.err.println( "Can not set email by given id!" );

employee = null ;

e.printStackTrace();

}

return id;

}

/**

* 远程方法:查找所有的实体Bean对象

* @return 返回查找到的所有的实体Bean对象的id的集合,是Integer保存的

*/

public Collection findAllEmployees(){

Vector allId = new Vector();

EmployeeHome employeeHome = this .getEmployeeHome();

try {

if (employeeHome!= null ){

Collection allEmployee = employeeHome.findAllEmployees();

Iterator iterator = allEmployee.iterator();

while (iterator.hasNext()){

Employee employee = (Employee) iterator.next();

allId.add( new Integer(employee.getId()));

} //end while

} //end if

} catch (Exception e) {

System.err.println( "FindAllEmployees Caught Exception!" );

employeeHome = null ;

e.printStackTrace();

}

return allId;

}

/**

* 远程方法:给出name查找所有对应的实体Bean对象

* @param name:给定的name

* @return 返回查找到的所有的实体Bean对象的id的集合,是Integer保存的

*/

public Collection findAllEmployeesByName(String name){

Vector allId = new Vector();

EmployeeHome employeeHome = this .getEmployeeHome();

try {

if (employeeHome!= null ){

Collection allEmployee = employeeHome.findByName(name);

Iterator iterator = allEmployee.iterator();

while (iterator.hasNext()){

Employee employee = (Employee) iterator.next();

allId.add( new Integer(employee.getId()));

} //end while

} //end if

} catch (Exception e) {

System.err.println( "findAllEmployeesByName Caught Exception!" );

employeeHome = null ;

e.printStackTrace();

}

return allId;

}

/**

* 远程方法:给出email查找所有对应的实体Bean对象

* @param email:给定的email

* @return 返回查找到的所有的实体Bean对象的id的集合,是Integer保存的

*/

public Collection findAllEmployeesByEmail(String email){

Vector allId = new Vector();

EmployeeHome employeeHome = this .getEmployeeHome();

try {

if (employeeHome!= null ){

Collection allEmployee = employeeHome.findByEmail(email);

Iterator iterator = allEmployee.iterator();

while (iterator.hasNext()){

Employee employee = (Employee) iterator.next();

allId.add( new Integer(employee.getId()));

} //end while

} //end if

} catch (Exception e) {

System.err.println( "findAllEmployeesByEmail Caught Exception!" );

employeeHome = null ;

e.printStackTrace();

}

return allId;

}

}

•  然后把增加的一些 public 方法提升至远程方法,把下列方法提升至远程方法:

createOneEmployee ()、 getNameById 、 getEmailById 、 setNameById 、 setEmailById 、 findAllEmployees 、 findAllEmployeesByName 、 findAllEmployeesByEmail ,提升后,屏幕左下角的轮廓视图如下图所示:

紧接着,对此 SessionBean 进行生成部署代码,在 j2ee 视图中的层次结构下,选中 EmployeeSession ,点右键,生成部署代码,如下图所示:

•  注意,我们在上面的 SessionBean 中访问实体 Bean ,是通过查找实体 Bean 的实际的 jndi 名字来获得对实体 Bean 的引用的。同时,实体 Bean 引用数据库连接池也是使用数据库连接的 jndi 名字来引用数据库连接的。

然而,在许多时候,我们可以使用“资源映射”来访问实体 Bean ,也就是说: SessionBean 在访问实体 Bean 的时候,采用 lookup(“java:comp/env/Employee”) 来查找实体 Bean ,而这里的查找是采用 j2ee 推荐的标准名字空间,这里的 Employee 是一个别名,在这里它对应着我们的 Employee 实体 Bean ,这个对映关系由资源映射符来确定,也就是说资源映射符定义了这里的别名 Employee 和实体 Bean 的 Employee 的 jndi 之间的对应关系。这种使用方式的优点是,在程序中可以写死调用的别名,具体实际调用的是哪一个 EJB 由布署时在资源映射符中定义。

如果你接受以上用法会给你的 EJB 开发和部署带来好处,那么请继续看下去如何做来定义这些资源引用,如果你不接受这个观点,你认为在程序中将 EJB 的 jndi 名字写死,那么请跳过下一段,直接进入 18 小节阅读。

好,下面我们来看如何修改我们的 SessionBean ,使之采用资源映射的方式来访问我们的实体 Bean 。第一步,修改代码,打开 EmployeeSessionBean.java 文件,找到其中的:

private EmployeeHome getEmployeeHome() 方法,把它修改成如下所示:

private EmployeeHome getEmployeeHome(){

InitialContext initialContext = null ;

EmployeeHome employeeHome = null ;

try {

initialContext = new InitialContext();

//Object employeeHomeObject = initialContext.lookup("ejb/com/employee/entity/EmployeeHome");

//采用资源引用,不直接采用jndi查找

Object employeeHomeObject = initialContext.lookup( "java:comp/env/EmployeeRef" );

employeeHome = (EmployeeHome)PortableRemoteObject.narrow(employeeHomeObject,EmployeeHome. class );

} catch (NamingException e){

System.err.println( "CaughtException:" +e.toString());

employeeHome = null ;

e.printStackTrace();

} finally {

if (initialContext!= null )

try {

initialContext.close();

} catch (NamingException e) {

}

}

return employeeHome;

}

在上面的代码中,我们只修改了一句,把原来采用 jndi 来查找实体 Bean 的方法改为了采用资源引用的方式,在这里,我们用 EmployeeRef 这个别名来引用实体 Bean 。

下面我们来修改部署描述符文件,增加资源引用部分。在 WSAD 左边 j2ee 视图中的 j2ee 层次结构视图中,打开 EJB 模块下的会话 Bean ,双击其下的 EmployeeSession ,在右边的视图中打开其部署描述符文件,选择“引用”页面,如下图所示:

选择 EmployeeSession ,然后单击其下方的“添加”按钮,如下图所示:

选中“ EJB ”引用,点击“下一步”,如下图所示:

在上图中,选择“当前 EJB 项目中的企业 bean ”,然后在列表中选择中“ Employee ”,并把系统在“名称”中填入的 ejb/Employee 修改为“ EmployeeRef ”,这是我们在程序中引用的别名。然后点“下一步”,并在下一步中点“完成”。重新回到了部署描述符文件中。如下图所示:系统自动填写完毕。

保存并退出部署描述符修写。

重新生成 EmployeeSession 的部署代码,并重新编译 EJB 。

•  然后,我们可以像第 11 步中那样启动通用测试客户机来测试我们的的 SessionBean 。在 J2ee 视图中的 j2ee 层次结构中,选中 EmployeeSession ,点右键,在服务器上运行即可。 •   

•  性能优化,在这一小节中,我们来看看如何优化 SessionBean 来调用实体 Bean 的性能,由于 SessionBean 通过远程接口 lookup 实体 Bean ,所以大部分时间均发在 lookup 上面了。为了优化 SessionBean 调用实体 Bean 的性能,我们在这里给出一个参考方案即采用“重用 Home 句柄”技术。也就是将需要在 SessionBean 中调用的实体 Bean 的 home 句柄用缓存保存起来,为了达到这个目地,我们需引入单根模式来设计一个 EjbHomeCacheHelper 类。

在 j2ee 视图中,像前面编写 SessionBean 一样,新建一个包并命名为: com.ejbhome.helper ,然后再在此包在新建一个类,并命名为: EjbHomeCacheHelper ,其全部代码如下:(其代码是自解释的)

package com.ejbhome.helper;

import java.util.Hashtable;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.rmi.PortableRemoteObject;

import com.employee.entity.EmployeeHome;

/**

* @author abnerchai

* 本方法采用单根模式来存储所有的实体Bean的Home句柄,这样系统中有

* 多少个实体Bean,那么在本对象中就存储了多少个Home对象柄,在本对象

* 第一次初始化时就将所有的实体Bean的Home句柄保存起来放在内存中,下一次其它的

* SessionBean欲调用实体BEAN时,只需从内存中获得即可,这样可以大大提高调用的

* 速度和性能。

*/

public class EjbHomeCacheHelper {

//定义所有的对实体Bean的引用名字在这里,有几个实体Bean,这里就定义几个引用常量

private static final String EmployeeRef = "EmployeeRef" ;

//采用单根模式

private static EjbHomeCacheHelper ejbHomeCache = null ;

//定义保存所有Home句柄引用的表

private Hashtable ejbHomeTable = new Hashtable();

//采用单根模式,将构造器设置为私有的

private EjbHomeCacheHelper(){

}

//返回表

private Hashtable getejbHomeTable(){

return ejbHomeTable;

}

private synchronized static EjbHomeCacheHelper getInstance(){

if (ejbHomeCache == null ){ //第一次运行为空,便构建一个,以便所有的共享

ejbHomeCache = new EjbHomeCacheHelper();

//构建实体BEAN柄集合

ejbHomeCache.buildHomeHandleCache();

}

return ejbHomeCache;

}

//构建出所有的实体Bean的Home句柄的集合并保存起来

private void buildHomeHandleCache(){

Context ctx = null ;

Object homeObject = null ;

EmployeeHome employeeHome = null ;

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.ibm.websphere.naming.WsnInitialContextFactory" );

try {

ctx = new InitialContext(env);

homeObject = ctx.lookup( "java:comp/env/EmployeeRef" );

employeeHome = (EmployeeHome)PortableRemoteObject.narrow(homeObject,EmployeeHome. class );

getejbHomeTable().put(EmployeeRef,employeeHome);

//可以在这里加入其它的对实体Bean的引用并把它放入cache表中,需要引用几个实体Bean,

//这里就加上几个查找并put的方法

} catch (Exception e){

e.printStackTrace();

} finally {

if (ctx!= null ){

try {

ctx.close();

} catch (NamingException e1) {

e1.printStackTrace();

}

} //end if

} //end finally

} //end buildHomeHandleCache

//以下所有的方法对外开放,用于外部引用实体Bean时获得实体Bean的Home句柄

//有几个实体Bean,这里就定义几个方法

public static EmployeeHome getEmployeeHome(){

return (EmployeeHome)getInstance().getejbHomeTable().get(EmployeeRef);

}

} //end class

然后,我们就采用这个工具类来调用我们的实体 Bean 了,在 EmployeeSessionBean.java 文件中新增一个方法:名字为: getEmployeeHomeFromCache() ,其内容如下:

/**

* 私有方法,通过实体Bean缓存来获得EmployeeHome接口

* 可以大大提高性能

* @return 返回实体Bean的Home接口对象

*/

private EmployeeHome getEmployeeHomeFromCache(){

return EjbHomeCacheHelper.getEmployeeHome();

}

即可。在需要调用实体 Bean获得Home的地方,采用此方法替换即可。

•  下面我们来开发一个 JavaBean 和一个 JSP 页面来调用我们的 EJB ,过程如下:

在 J2ee 视图中,点菜单中的“文件” -> “新建” -> “项目”,如下图所示:

选择左边的 WEB ,选择中右边的“动态 Web 项目” , 点下一步。如下图所示:

在项目名中填写 HelloWorldWebProject ,并选择中“配置高级选项”然后点“下一步”即可如下图所示:

按上图中所示选择 EAR 项目为己有的 HelloWorldEARProject ,上下文根不变即可。然后点“下一步”,如下图所示:

在上图中什么也不选择,直接点击“完成”,在弹出的两个如下图所示的对话框中,选择“确定修改服务器配置”和“不切换到 WEB 视图”即可。

然后,在 WSAD 左边 J2ee 视图中出现了如下图所示的情况:

在上图中,在当前 EAR 项目中新建了一个 WEBProject 项目,这个 WEB 项目下面包括两部分:一个是 Java Source ( Java 资源),另一个是 Web Content 。前者用于管理和存放 JavaBean 及 Servlets ,后者用于存放和管理 JSP 及 HTML 等页面文件。

接着在上图中,右键选中“ java 资源”,点击右键菜单中,选择“新建” -> “包”如下图所示:

弹出如下图所示对话框:

在上图中名称栏中输入: ”com.employee.bean” 包名。点完成即可。然后再在左边的 J2ee 视图中选择刚建好的包,点右键,“新建” -> “类”如下图所示:

弹出如下图所示对话框:

在此图中,名称一栏中填入“ EmployeeJavaBean ”做为我们的 JavaBean 名字,然后点“完成”即可打开编辑这个 JavaBean 的代码窗口。

此时,右键点击 J2ee 视图中的 EmployeeWebProject ,选择“属性”,然后在弹出的对话框中左边选择“项目引用”,如下图所示:

右边请选择中 HelloWorldEJBProject ,。接着,选择这个图左边的“ Java 构建路径”,在右边出来的窗口中选择中“项目”一页,如下图所示:

在上图中选中“ HelloWorldEJBProject ”,然后点确定。这样一来,我们的 WEB 项目就可以调用 EJB 了。下面我们来编写 javaBean 我们这个 EmployeeJavaBean 是用来提供给 JSP 页面来调用 EJB 的。编写后的代码如下所示:

package com.employee.bean;

import java.rmi.RemoteException;

import java.util.Hashtable;

import javax.ejb.CreateException;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.rmi.PortableRemoteObject;

import javax.servlet.http.HttpServletRequest;

import com.employee.session.EmployeeSessionHome;

import com.employee.session.EmployeeSession;

public class EmployeeJavaBean {

private HttpServletRequest _request = null ;

public void init(HttpServletRequest req){

this ._request = req;

}

private EmployeeSession getEmployeeSession(){

Context ctx = null ;

Object homeObject = null ;

EmployeeSessionHome employeeSessionHome = null ;

EmployeeSession employeeSession = null ;

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.ibm.websphere.naming.WsnInitialContextFactory" );

try {

ctx = new InitialContext(env);

homeObject = ctx.lookup( "ejb/com/employee/session/EmployeeSessionHome" );

employeeSessionHome = (EmployeeSessionHome)PortableRemoteObject.narrow(homeObject,EmployeeSessionHome. class );

employeeSession = employeeSessionHome.create();

} catch (Exception e){

e.printStackTrace();

} finally {

if (ctx!= null ){

try {

ctx.close();

} catch (NamingException e1) {

e1.printStackTrace();

}

} //end if

} //end finally

return employeeSession;

}

public String getNameByEmployeeID(){

String id = this ._request.getParameter( "ID" );

if (id== null ) return null ;

int int_id = Integer.parseInt(id);

String name = null ;

try {

name = this .getEmployeeSession().getNameById(int_id);

} catch (RemoteException e) {

e.printStackTrace();

}

return name;

}

}

注意,为了演示,我在 JavaBean 中只编写了一个方法,该方法来调用 SessionBean 中的方法。

下面我们新建一个 JSP 文件,来调用我们的 JavaBean ,过程如下:

在 J2ee 视图中,右键选中 WebContent , ” 新建 ”-> “ JSP 文件”如下图所示:

在弹出的对话框中如下图:

填入文件名为 index.jsp 。然后点击完成。进入编辑 JSP 页面。

修改后的 JSP 文件代码如下所示:

<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >

< HTML >< HEAD >

<%@ page language = "java" contentType = "text/html; charset=GBK" pageEncoding = "GBK" %>

< jsp:useBean id = "employeeJB" class = "com.employee.bean.EmployeeJavaBean" scope = "page" ></ jsp:useBean >

< META http-equiv = "Content-Type" content = "text/html; charset=GBK" >

< META name = "GENERATOR" content = "IBM WebSphere Studio" >

< TITLE > index.jsp </ TITLE >

</ HEAD >

< BODY >

<%

String name = null ;

if (request.getMethod().equalsIgnoreCase( "post" )){

employeeJB.init(request);

name = employeeJB.getNameByEmployeeID();

}

%>

< p > 请输入你要查找的ID: </ p >

< form name = "base" method = "POST" action = "index.jsp" >

< input type = "text" value = "" name = "ID" >

< input type = "submit" value = "查找!" >

</ form >

<%

if (name!= null ){

out.println( "<p>你查找的名字是:" +name+ "</p>" );

}

%>

</ BODY >

</ HTML >

•  测试: 启动服务器,在 IE地址栏中输入: http://localhost:9080/HelloWorldWebProject/index.jsp ,在输入框中输入1,运行如下图所示:

•  这里,我们的 JavaBean采用的是直接调用SessionBean,在实际的运用中,我们也可以采用前面所说的“重用Home句柄”的方法来提搞性能。

首先,我们修改我们的 JavaBean,使其采用资源引用的方式来调用SessionBean,方法如下:

打开 EmployeeJavaBean .java文件,修改其中的 private EmployeeSession getEmployeeSession() 方法。把这个方法中的:

homeObject = ctx.lookup("ejb/com/employee/session/EmployeeSessionHome");

替换为:

homeObject = ctx.lookup("java:comp/env/EmployeeSessionRef");

然后,再在左边 J2ee视图中,双击打开 ” WEB CONTENT ” 目录下的 ” WEB-INF ” 目录下的 web.xml,启动WEB部署符编辑器,然后选择中页面“引用”如下图所示:

在上图中,单击“添加” ,并修改自动产生的引用的名字为:“ EmployeeSessionRef ”,然后选中它,在右边的框中输入必要的信息,方法如下:在链接右边单击“浏览”,弹出如下图所示的对话框:

双击图中的 EmployeeSession,即可。WSAD自动把图中的框填充完毕。如下图所示,保存即可。

至此,我们己把 JavaBean调用SessionBean改为了资源引用的方式。

下面,我们来采用“重用 Home句柄”的方式来优化JavaBean调用SessionBean的性能。

•  为了提高 JavaBean调用SessionBean(EJB)的性能,采用同样的方式,我们先在“Java资源”下新建一个包并命名为:com.bean.ejbhelper,并在包中新建一个类,命名为: EjbHomeFindCacheHelper

其源代码如下:

package com.bean.ejbhelper;

import java.util.Hashtable;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.rmi.PortableRemoteObject;

import com.employee.session.EmployeeSession;

import com.employee.session.EmployeeSessionHome;

public class EjbHomeFindCacheHelper {

//定义所有的对SessionBean的引用名字在这里,有几个SessionBean,这里就定义几个引用常量

private static final String EmployeeSessionRef = "EmployeeSessionRef" ;

//采用单根模式

private static EjbHomeFindCacheHelper ejbHomeCache = null ;

//定义保存所有Session句柄引用的表

private Hashtable ejbHomeTable = new Hashtable();

//采用单根模式,将构造器设置为私有的

private EjbHomeFindCacheHelper(){

}

//返回表

private Hashtable getejbHomeTable(){

return ejbHomeTable;

}

private synchronized static EjbHomeFindCacheHelper getInstance(){

if (ejbHomeCache == null ){ //第一次运行为空,便构建一个,以便所有的共享

ejbHomeCache = new EjbHomeFindCacheHelper();

//构建SessionBean句柄集合

ejbHomeCache.buildHomeHandleCache();

}

return ejbHomeCache;

}

//构建出所有的SessionBean的Home句柄的集合并保存起来

private void buildHomeHandleCache(){

Context ctx = null ;

Object homeObject = null ;

EmployeeSessionHome employeeSessionHome = null ;

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory" );

try {

ctx = new InitialContext(env);

//通过在web.xml中配置资源引用来查找EJB

homeObject = ctx.lookup( "java:comp/env/" +EmployeeSessionRef);

employeeSessionHome = (EmployeeSessionHome)PortableRemoteObject.narrow(homeObject,EmployeeSessionHome. class );

getejbHomeTable().put(EmployeeSessionRef,employeeSessionHome);

//可以在这里加入其它的对SessionBean的引用并把它放入cache表中,需要引用几个SessionBean,

//这里就加上几个查找并put的方法

} catch (Exception e){

e.printStackTrace();

} finally {

if (ctx!= null ){

try {

ctx.close();

} catch (NamingException e1) {

e1.printStackTrace();

}

} //end if

} //end finally

} //end buildHomeHandleCache

//以下所有的方法对外开放,用于外部引用实体Bean时获得实体Bean的Home句柄

//有几个实体Bean,这里就定义几个方法

public static EmployeeSessionHome getEmployeeSessionHome(){

return (EmployeeSessionHome)getInstance().getejbHomeTable().get(EmployeeSessionRef);

}

}

定义好了这个类以后,我们再次修改我们的 JavaBean,打开 EmployeeJavaBean .java文件,增加一个方法如下:

private EmployeeSession getEmployeeSessionByCache(){

EmployeeSessionHome employeeSessionHome = null ;

EmployeeSession employeeSession = null ;

employeeSessionHome = EjbHomeFindCacheHelper.getEmployeeSessionHome();

try {

employeeSession = employeeSessionHome.create();

} catch (Exception e) {

e.printStackTrace();

}

return employeeSession;

}

即可,然后把原来调用 getEmployeeSession ()的地方改为 getEmployeeSessionByCache ()即可。

测试方法同前一样 ,在此不再详解。最后,你的工作区形成了如下图所示的情况:

•  到此为止,我们详细说明了一个 CMP实体Bean的开发过程及其客户端的开发过程。

希望你能有所收获。任何意见和建议请和我联系。

四、Copyright

Copyright by abnerchai, 2004. you can contact me at: [email protected]

你可能感兴趣的:(bean,exception,null,性能优化,sqlserver,import)