服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

ejb 访问代理设计常用的访问方式


  常规访问方式
  编写过ejb(enterprise java bean)访问程序的朋友都知道,通过客户端或服务端的程序访问ejb(即获得一个ejb remote或local对象)通常要经历以下几个步骤:
  
  (1)创建一个初始化上下文(initial context);
  
  (2)通过jndi查找对应的ejb上下文对象;
  
  (3)通过获得的上下文对象获得一个home或者localhome对象(获得home对象通过portableremoteobject对象的narrow方法,获得localhome对象通过强制类型转换);
  
  (4)最后通过home或localhome的create方法创建一个remote或local对象,通过remote或local对象真正使用服务器的ejb提供的方法。
  
  代理类设计
  如果我们能够把以上4个步骤封装在一个类(本文叫ejbagent)的方法(getremote和getlocal)内就可以使得获得一个remote或local对象只需要提供一个jndi的名称,避免了重复拷贝以上4个步骤的代码。写过ejb访问代码的程序员都知道,1~3步是很容易封装起来的,以下是典型的代码:
  
  /*1.*/ initialcontext context = new initialcontext (properties);
  
  /*2.*/ object home = context.lookup(jndiname);
  
  /*3.*/ ejbhome ejbhome =
  
  (ejbhome) portableremoteobject.narrow (home, ejbhome.class);
  
  第一步获得一个context,主要是获得应用服务器的环境参数,我们可以把存放环境变量的pertieserties对象作为参数,第二步是查找ejb上下文对象,可以把jndiname作为参数,第三步获得home对象,我们可以统一获得home对象的父类:ejbhome,应用程序在具体根据实际使用的home接口作类型转换。
  
  第四步通过create方法创建一个remote或local对象封装就有一定困难了,因为我们在第三步获得的是一个ejbhome的接口,而我们知道,ejbhome接口本身不提供create方法(对entitybean有可能是findbyprimarykey的方法),而是由具体的应用程序的home接口定义的,所以如果我们直接在代码体写ejbhome.create(),会产生一个编译错误,提示方法create没找到。要使程序能够执行create方法,一种办法是把ejbhome强制类型转换成应用程序定义的ejbhome类型,即(ejbhome)换成(ejbexamplehome),其中ejbexamplehome是应用程序定义的ejbhome接口,但这样必须在代码体中写入应用程序定义的ejbhome类名称,达不到通用处理的目的。但我们知道,通过portableremoteobject.narrow出来的ejbhome其实是应用程序的定义的home接口,即虽然我们使用(ejbhome)作类型转换,但ejbhome实际指向的对象是ejbexamplehome,其中就定义create方法,我们可以采用动态调用的方式调用create方法,从而避免在编译时产生错误。java.lang.reflect包提供了通过方法名称动态调用方法的method类。以下代码是上述思想的实现:
  
  /*3.*/ ejbhome ejbhome =
  
  (ejbhome) portableremoteobject.narrow (home, ejbhome.class);
  
  /*4.*/ class ejbhomeclass = ejbhome.getclass();
  
  /*5.*/ method method = ejbhomeclass.getdeclaredmethod("create",null);
  
  /*6.*/ object remoteobject = method.invoke(ejbhome,null);
  
  其中第4步是获得ejbhome的class,可能有部分朋友以为是获得ejbhome的类,其实获得的class是应用程序定义的ejbhome接口:应用程序定义的类ejbexamplehome。有兴趣的读者可以通过getname()方法获得实际class名称作判断。第五步通过获得的class获得一个定义的create方法。getdeclaredmethod有两个参数,第一个是方法的名称,是string类型,第二个是参数类型,是class数组。由于create方法是没有参数,所以getdeclaredmethod第二个参数是null。需要注意的是getdeclaredmethod是动态执行的,所以第一参数:方法名称如果写错,编译时是不会产生错误的,在实际执行时才会报错,抛出“没有该方法”的异常:nosuchmethodexception。第6步通过动态调用create方法创建remote对象。与getdeclaredmethod方法对应,method的invoke方法也有两个参数,第一个参数是定义执行方法的对象,object类型,第二个参数是调用方法的参数,是object数组,因为create方法没有参数,所以第二个参数设置为null。
  
  例子介绍
  以下以weblogic6.1作应用服务器为例子说明ejbagent的使用方法。我们建立一个叫ejbexample的sessionbean,其home接口为ejbexamplehome,remote对象为ejbexampleremote,其jndi名称为ejbexample。通过以下代码体获得一个ejbexampleremote的对象:
  
  properties properties = new properties();
  
  properties.put(context.initial_context_factory, "weblogic.jndi.wlinitialcontextfactory");
  
  properties.put(context.provider_url,"t3://localhost:7001";);
  
  ejbagent agnet = new ejbagent(properties);
  
  ejbexampleremote remote = (ejbexampleremote)agent.getremote("ejbexample");
  
  通过获得的remote对象就可以操作服务器端ejbexample的方法。我们可以看到,整个过程只需要两个参数:应用服务器环境properties和对应的ejb jndi名称,强制类型转换也只需要在获得remote对象时才使用到。而且通常一个应用程序是连接到一个应用服务器上,所以properties参数通常只需要设置一次,这样可以只产生一个ejbagent实例供多个客户端程序使用,既减少了代码量,也提高了重用性。如果我们想获得的是一个local对象,则可以不必构造一个properties对象作为参数,为获得local对象的程序通常是运行在应用服务器端的sessionbean,直接使用new initialcontext()则可以获得应用服务器的环境参数。所以ejbagent提供了有参和无参两个构造方法,分别供client端和application server端的应用程序使用。具体的实现请看ejbagnet.java。下面就ejbagnet的部分关键代码作说明:
  
  (2)以静态static的方式定义ejbagent使用的context对象:避免ejb访问程序多次重新获得context。在局域网的环境中,从clinet获得一个context的时间在1~3秒范围内,笔者在局域网用weblogic6.1作应用服务器作过时间比较,获得一个context平均花1.3秒,而获得一个home和remote对象只分别花17和36毫秒,所以把获得的context用静态方式缓存以供调用时使用大大减少了应用程序访问ejb的时间;
  
  (2)针对entity bean的访问增加了getremotebykey和getlocalbykey的方法,可以通过jndi name和primary key的对象获得一个entitybean remote或local对象,同样通过动态调用的方式实现。与create方法创建ejb的区别是findbyprimarykey的方法需要有参数调用。

扫描关注微信公众号