用 WSAD5.0和SQLServer2K采用Meet-in-Middle模式开发
|
接上篇: 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的开发过程及其客户端的开发过程。 希望你能有所收获。任何意见和建议请和我联系。 四、CopyrightCopyright by abnerchai, 2004. you can contact me at: abnertsai@sina.com |
相关推荐
汇川AM系列ethercat控制伺服的使用说明(含转矩模式)
本文以一个实际例子,介绍ethercat伺服驱动器的工作原理,以及在汇川AM系列PLC中,如何点动、定位、速度、转矩控制ethercat伺服。
用 WSAD5.0和SQLServer2K采用Meet-in-Middle模式开发CMP实体Bean及其完整客户端(上篇:CMP的开发)
无标题文档 用 WSAD5.0和SQLServer2K采用Meet-in-Middle模式 开发CMP实体Bean及其完整客户端 (上篇:CMP的开发) abnerchai( 柴政 ) 2004 年 6 月 说明: 在许多情况下,我们现在还常常使用 CMP 实体 Bean ,而 IBM 的 WebSphere Studio Application Developer5.0
YOLOv12模型详解及代码复现
YOLOV12算法详解及Python代码复现
理解和正确使用Java中的断言(assert)
理解和正确使用Java中的断言(assert) 一、语法形式: Java2在1.4中新增了一个关键字:assert。在程序开发过程中使用它创建一个断言(assertion),它的语法形式有如下所示的两种形式:1、assert condition; 这里condition是一个必须为真(true)的表达式。如果表达式的结果为true,那么断言为真,并且无任何行动如果表达式为false,则
深入剖析Java编程中的中文问题及建议最优解决方法--上篇
深入剖析Java编程中的中文问题及建议最优解决方法--上篇 说明:本文为作者原创,作者联系地址为:josserchai@yahoo.com。由于Java编程中的中文问题是一个老生常谈的问题,在阅读了许多关于Java中文问题解决方法之后,结合作者的编程实践,我发现过去谈的许多方法都不能清晰地说明问题及解决问题,尤其是跨平台时的中文问题。于是我给出此篇文章,内容包括对控制台运行的class、
Jbuilder9.0+jboss-3.2.1_tomcat-4.1.24.zip+MySql/MS SQL Server2K开发环境配置手记
Jbuilder9.0+jboss-3.2.1_tomcat-4.1.24.zip+MySql或MS SQL Server2K开发环境配置手记 网络上对Jbuilder9.0+JBOSS-3.2开发环境的配置说明的参考还很少,我在这里提供一个,请大家参考,并指教!这是我在配置这个开发环境时的一个手记。下面是详细步骤: 1、 安装Jbuilder9.0到D:/Jbuilder9目录2、 安
win2k环境下基于JBOSS的J2EE开发实践----之一初始基础环境的配置与测试
JBOSS开发实践 基于 win2k环境下的JBOSS开发实践 之一:初始基础开发环境的配置与测试 说明: 此节针对 ejb 开发初学者,主要是手动配置一个最基本的基于文本开发的环境,让初学者从头开始编写各类程序和配置文件,以更清楚的了解 EJB 开发和部署的步聚与原理。这是作者在学习 EJB 开发时的一个总结,欢迎指正。作者联系地址址: josse
深入剖析Java编程中的中文问题及建议最优解决方法---下篇
New Document 深入剖析Java编程中的中文问题及建议最优解决方法 说明:本文为作者原创,作者联系地址为:josserchai@yahoo.com。由于Java编程中的中文问题是一个老生常谈的问题,在阅读了许多关于Java中文问题解决方法之后,结合作者的编程实践,我发现过去谈的许多方法都不能清晰地说明问题及解决问题,尤其是跨平台时的中文问题。于是我给出此
win2k环境下基于JBOSS的J2EE开发实践----之五:CMP实体Bean的编写与部署
win2k环境下基于JBOSS的J2EE开发实践 ----之五:CMP实体Bean的编写与部署一、 前言在前面一系列文章的上一节中,我们给出了编写BMP的方法,并详细述说了BMP与CMP的区别和共性。BMP和CMP同属EJB2.x规范中定义的实体Bean(Entity Bean),一个实体Bean是由多个类和接口组成,我们可以认为一个实体Bean代表数据库中的一个表(姑且这么认为),一个实体Bea
win2k环境下基于JBOSS的J2EE开发实践----之四:BMP实体Bean的编写与设计
win2k环境下基于JBOSS的J2EE开发实践 ----之四:BMP实体Bean的编写与设计说明:本教程发表于csdn.net网站(中国程序员网)文档中心,任何人转载请注明出处,并且保留此说明。作者本人在发表此系列文章后,许多网友来信要求作者继续编写此教程,作者在此处首先感谢广大网友的信任!作者联系地址为:josserchai@yahoo.com。前言: 在《WIN2k环境下基于JBOS
深入理解嵌套类和内部类
深入理解嵌套类和内部类 一、什么是嵌套类及内部类? 可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型:静态嵌套类和非静态嵌套类。静态嵌套类使用很少,最重要的是非静态嵌套类,也即是被称作为内部类(inner)。嵌套类从JDK1.1开始引入。其中inner类又可分为三种: 其一、在一个类(外部类)中直接定义的内部类; 其二、在一个方法(外
win2k环境下基于JBOSS的J2EE开发实践----之三、有状态会话 Bean的开发及多种调用有状态会话Bean方法的实现
win2k环境下基于JBOSS的J2EE开发实践 ----之三、有状态会话 Bean的开发及多种调用有状态会话Bean方法的实现 说明:此节是继上一节之后所写,在上两节中我们实现了 JBOSS 开发平台的配置及数据库连接池的配置,同时我们在第一节的示例中,给出了一个无状态会话 Bean 的实例 HelloWorld 。这一节中我们接着学习 EJB 开发。 注意:本
win2k环境下基于JBOSS的J2EE开发实践-----之二、数据库连接池的配置与测试
JBOSS开发实践 基于 win2k环境下的JBOSS开发实践 之二、数据库连接池的配置与测试 说明:此节是在上一节基础之上写的,上一节中我们把JBOSS服务器配置好,并测试通过了。这一节我们来看看怎么样在JBOSS中 用Jsp和Servlet连结数据库,并使用它的连接池,你一定要在看完上节后再看这一节。 一、配置MySQL数据库 1、安装
一个经试用效果非常不错的数据库连接池
无标题文档 一个经试用效果非常不错的数据库连接池 前言: 虽说现在许多企业级的应用服务器均自己带有数据库连接池功能,就连 Tomcat 也支持了这种功能。然而在许多时候,我们还是要使用数据库连接池,如:访问数据库的 Java 桌面应用程序等。这个数据库连接池是我根据《 Inside Servlets 》一书中的示例改写而成,经过试用,效果非常不错。特发布共享。 ( 作者
JAVA中通用JPEG缩影图Bean的制作与示例
JAVA中通用JPEG缩影图Bean的制作与示例 JAVA中通用JPEG缩影图Bean的制作与示例 说明: 前一段时间,看到网上一个网友贴出一个用 Java 跨平台的生成 Jpeg 图片缩影图的方法。最近整理了一下,形成了一个通用的类。并制作成一个 jar 包。以方便重用。并给出了使用示例。(作者: abnerchai ;联系: josserchai@yahoo.com
Tomcat7.0.40 基于DataSourceRealm的和JDBCRealm的资源用户访问控制
软件版本: Tomcat 7.0.40 Mysql: 5.1 Host: CentOS 6.3 64bit 使用JDBCRealm (Tomcat 会使用所给的JDBC Connecter 自己去连MySQL 数据库并进行用户验证): 1) 下载MySQL-JDBC connector 如mysql-connector-java-5.1.24-bin.jar放到$CATALI
直播APP如何兼顾画质与低延迟?视频美颜SDK性能优化开发思路
直播APP既要高清画质,又要低延迟和流畅体验,美颜SDK的性能优化就成为关键环节。本文从视频处理链路、GPU加速、人脸识别、动态降级、多机型适配等方面,分析直播APP开发中如何优化视频美颜SDK,在保证美颜效果的同时降低设备负载和处理延迟。
12-Rust 性能优化指南(性能分析 + 内存优化 + SIMD + 并发优化 + 编译器优化 + 基准测试)
本文系统讲解 Rust 性能优化核心知识,涵盖性能分析工具(perf、flamegraph、cachegrind)、内存优化(零拷贝、缓存友好、内存池)、SIMD 向量化、并发优化(线程池、无锁数据结构)、编译器优化标志、基准测试(criterion)等核心内容。每个知识点配有完整代码示例、对比表格、实战场景及常见问题解答,帮助开发者编写高性能 Rust 代码。
【ArkUI 练中学】第14课:应用性能优化实战
本文系统阐述ArkUI应用性能优化核心方法:以冷启动≤3000ms、点击响应≤1000ms、帧率≥60为目标,通过HiTrace+DevEco Profiler获取关键路径瀑布图,运用“延迟、并行、裁剪、预置”四步法优化启动链路。结合细粒度状态管理、组件拆分、@Reusable复用、LazyForEach懒加载等手段提升渲染效率,遵循扁平化布局原则减少重绘,利用工具链检测内存泄漏,实施资源压缩、HSP共享与分包策略降低包体积,并建立“分析—优化—验证”闭环,实现全链路性能治理。
第5板块·第4节:性能优化中的高级技巧
恭喜你完成第5板块「Kernel全方位性能优化(调优实战)」的全部内容!测量→假设→优化→验证迭代闭环;Nsight Systems / Compute工具分工。✅ 基于Profiling迭代实战:解读报告,针对内存/依赖/同步/执行单元各类Warp停滞做针对性优化;识别调优陷阱。✅ 典型算子深度优化:GEMM多级优化、im2col卷积、FlashAttention分块重计算思想。cp.async异步拷贝流水线双缓冲;CUDA Graph消除Kernel启动开销;多流并发;架构适配;
【ArkUI 练中学】第18课:性能优化进阶与工程化治理
本文系统介绍了HarmonyOS应用性能治理全链路方案:基于DevEco Profiler的场景化分析模板(如Launch、Frame、Time等)实现精准问题定位;通过深度录制与跨语言调用栈分析优化关键路径;结合Test Kit与DevEco Testing构建白盒自动化测试与性能基线;利用HiAppEvent+AGC APMS实现线上启动耗时、崩溃率等指标监控;针对折叠屏等多设备形态,采用响应式布局与布局重算控制策略;最终将性能门禁融入CI/CD,形成“开发—测试—上线”闭环治理能力,助力中型应用实现高






























5061


&spm=1001.2101.3001.11974&articleId=24248&d=1&t=3&u=f2367b4db79c4e95a2739c2e7c46e218)

被折叠的 条评论
为什么被折叠?



