使用 Local 与 LocalHome 访问 EJB 组件 -- 解惑篇

    这个年代还在写EJB 2.1的东西感觉很怪,毕竟我在网上寻找答案的时候发现绝大多数提问的帖子都是04年以前的了,如今也没什么人还会用EJB 2.1以下的版本做项目。然而,实际生产总是跟不上潮流的,公司里需要我维护的还是EJB 1.x 与 2.x 的系统呢,不学也是没办法。

   

    写这篇文章,一来是为了帮自己记着点,二来是看到相关问题在网上总是找不到满意的答案,被提问的高手(或假高手)大都语焉不详,解释了半天也没提供一点可操作性,甚是失望。查书的结果也让人沮丧。死样活气的 “NameNotFoundException” 简直把人气到无语。如今把搜索了好几天、研究了好几天的成果写下来,只怕不会因为它基础、简单而毫无价值。废话少说,开始吧。



    1. 要使用本地接口访问 EJB,首先自然是在 ejb-jar.xml 里面规定 <local> 和 <local-home> 接口的类(当然前提是你已经写好了这两个接口,不要笑,不少初学都会摆这个乌龙)。这里需要注意的是, EJB 2.x 的规范是不允许同时配置本地和远程接口的,你只能选择其中一个,这一点只要在一个有 xml 检查机制的编辑器(如 MyEclipse 自带的编辑器,或者大名鼎鼎的 XMLSpy )里就可以看出来。


    2. 其次,在客户端(我一般是用 servlet,jsp 也可以。注意不能用独立客户端,它只能用远程方式访问 EJB )写调用代码。写法99%和远程访问差不多,需要改的地方只有三个:

         a) 所有的接口引用都改成对应的本地接口,如 ProductHome --> ProductLocalHome, Product --> ProductLocal 等。

      b) PortableRemoteObject.narrow() 方法不需要了,直接强制转型即可。参考这里的讨论: http://topic.csdn.net/t/20040419/09/2981624.html

      c) 在做 context.lookup() 的时候,查找字串必须是 "java:comp/env/xxx" 的格式,这里要注意 xxx 不再是所调 EJB 的 jndi 名了,你可以自由指定,原因后面再说。

 

    3. 配置 ejb-jar.xml 或 web.xml 文件。这一步最关键,因为大多数人都是在这里崩溃的,遇到 NameNotFoundException 一点都不美。这里到底是配置 ejb-jar.xml 还是 web.xml 呢,这就看你的“客户端”是什么了。如果你使用 session bean 来访问 entity bean (其实只要是两个EJB就适用,类型不限),那么就配置 ejb-jar.xml ; 如果用 servlet 或 jsp 来访问 EJB 就改 web.xml 。

       如果是 ejb-jar.xml, 则在<enterprise-beans><ejb>...</ejb></enterprise-beans> 中加入以下描述符;

       如果是 web.xml, 则在根标签<web-app>...</web-app> 中加入以下描述符;

 

  <ejb-local-ref>
      <ejb-ref-name>ejb/ProductLocal</ejb-ref-name>
      <ejb-ref-type>Entity</ejb-ref-type>
      <local-home>examples.cmp.ejb.ProductLocalHome</local-home>
      <local>examples.cmp.ejb.ProductLocal</local>
      <ejb-link>ProductEJB</ejb-link>
  </ejb-local-ref>

 

       这一段的作用是把一个本地 EJB 组件作为资源注入客户端的运行环境。标签里的具体内容仅作示例。 说明一下:

      1) <ejb-ref-name> 是客户端 lookup EJB 时的名字,也就是上面提到的 "java:comp/env/xxx" 里面的 xxx, 惯例是推荐前面都带一个ejb/ 的了,倒是无所谓。

      2) <ejb-link> 是该 EJB 资源的名字即它在自己的 ejb-jar.xml 里的<ejb-name>。

 

      到这里可能有人糊涂了,Jndi 在哪里呢?这正是本文的重点所在。事实上,通过本地接口来访问一个 EJB,客户端是不需要知道它的 Jndi 名字的,因为此时采用的是 link 的方式,通过 <ejb-link> 指定的相对路径来访问这个本地资源。与该 <ejb-link> 相对应的 <ejb-ref-name> 实质上就是客户端专有资源的一个 伪Jndi 名。真正的 Jndi 名只在远程调用的时候才有意义,那时候调用被调用双方的相对路径是未知的。 这里真伪 Jndi 有点像 成员变量 和局部变量的关系。

      那末,为什么我们在 lookup 的时候不能直接用 <ejb-ref-name> 里面的名字,而是还要加上 "java:comp/env/" 的前缀呢?粗糙点解释就是,这个前缀就是专门用来查找“伪Jndi”的。详细的讲解见 : http://www.blogjava.net/javababy/archive/2006/12/06/85881.html

 

     补充一点,由于 <ejb-link> 是本地相对路径的标识, 首先就限制了调用客户端和 EJB 必须位于同一个 application 即 ear 里。其次,如果 EJB 模块的 jar 包下面还有 包含 EJB 模块的 jar 包,在访问最里面的那个 EJB 的时候就需要把 jar 的路径也写进 <ejb-link> 里去,如 <ejb-link>SalesEJB.jar#ProductEJB.jar#ProductEJB</ejb-link>

 

    到这里,文章就算写完了。我是非常奇怪,这么一个基础而常见的问题,要找个现成的答案居然这么难。哎,很多人成了高手,就都忘了初学者的痛苦了,要知道,初学 EJB 2.x 可是 J2EE 世界里最恶心的事情之一,与智力无关,只是太麻烦了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值