开发具有本地接口的无状态session bean

当通过远程接口调用EJB时
首先客户端需要与ejb建立起socket通信,在通信管道上他们之间需要来回发送IIOP协议消息,因为数据要在网络进行传输,存放数据的java对象必须要进行序列化
开发具有本地接口的无状态session <wbr>bean
在这个过程中,有网络通信的开销、协议解析的开销、对象序列化的开销。因为ejb是分布式技术,它允许客户端与ejb应用在不同一机器上面,所以这些性能开销也是必然的


但是在实际生产中,不可避免这种情况:客户端与EJB应用运行在同一台机器上的同一个jboss中
那么这个时候客户端是否还有必要跟ejb之间走上面的网络通信呢?
这个时候的客户端与ejb是在同一个jvm内,他们之间完全可以通过内存进行交互,如果如此,完全可以避免上面流程的性能开销,所以引入了——本地接口

 

通过本地接口调用ejb,直接在内存交互,这样可以避免因网络通信所造成的各种性能开销,但有一点需要注意:
只有客户端与EJB应用都在同一个JVM内运行的时候,才能调用本地接口,否则只能调用远程接口
什么情况下客户端与EJB应用是在同一个JVM?
只要客户端与EJB发布在同一个jboss内,就可以认为他们在同一个JVM

---------------------------------------------------------------

在原有的HelloWorld项目中,修改HelloWorldBean.java
@Remote(HelloWorld.class)
修改为@Local(HelloWorld.class) 就可完成本地接口
具有本地接口的无状态bean已经被开发

运行ANT的deploy将EJB部署到jboss中,通过控制台可以看到ejb已经成功部署


当EJB部署成功,jboss会为这个本地接口,生成出一个JNDI名称
开发EJB的客户端http://blog.sina.com.cn/s/blog_8020e411010123yl.html博文中讲述了 jboss生成JNDI默认命名规则,这里不再赘述

这里生成的JNDI名称为:HelloWorldBean/local
在客户端,通过该JNDI名称,使用本地接口,访问EJB

 

扫描二维码关注公众号,回复: 705849 查看本文章

此时会报错,原因是客户端和EJB不在同一个JVM内

 

新建一个web项目,将其部署在jboss下,使客户端与EJB在同一个jboss中,方可使用本地接口

新建一个Test.jsp,将原EJBClient客户端代码,复制进来

并讲类引入进来(<%@ page import="java.naming.*"%>)

此时 HelloWorld helloWorld = (HelloWorld)cts.lookup("HelloWorldBean/local");的HelloWorld类不存在,由于不是同一个项目,所以需要将刚才的EJBClient的java Project导入进这个Web Project中

选中这个EJBClient的Web项目,右键,Properties

开发具有本地接口的无状态session <wbr>bean

选择刚才的EJB java Project,点OK

在Test.jsp页面,完整的导入:
<%@ page import="javax.naming.*,com.test.ejb3.HelloWorld" %>
<body>
    <%
     try{
   InitialContext cts = new InitialContext();
   //根据EJB的JNDI名称去寻找与这个名称绑定的EJB的待承担对象
   //如果找到了,就会返回给客户端
   //在客户端用接口文件去引用这个待承担对象
   HelloWorld helloWorld = (HelloWorld)cts.lookup("HelloWorldBean/local");
   out.println(helloWorld.getClass().getName()); //$Proxy3
   //通过这个对象,调用EJB业务方法
   out.println(helloWorld.sayHello("本地人")); //hello说:你好,世界!
  }catch(NamingException e){
   out.println(e.getMessage());
  }
     %>
  </body>

此时客户端应用已经开发完成,然后导出war文件

开发具有本地接口的无状态session <wbr>bean

将war文件,拷贝到jboss的发布目录下进行发布

 

如果:

InitialContext cts = new InitialContext();

为Application Server指定了JNDI名称,那此程序只能运行在这个Application Server中

如不写参数,则其构造函数自动寻找jndi的上下文信息,自动与其绑定

 

要注意:在EJBClient的Web项目下,引用的HelloWorld接口,并没有将它的class文件放入该web项目的classpath下

原因是:当加载到HelloWorld类时,没有找到它时,由于引用了HelloWorld JavaProject项目,EJB类加载器就会去它的classpath中寻找

所以,当WEB应用和EJB应用部署在同一个JVM内时,并不需要在客户端应用里面,放入EJB的接口类

如果将EJB接口类放入进客户端classpath中,有时会导致类型出图问题

 

企业中,很有可能客户端和EJB是部署在同一个JBOSS中,也可能部署在不同机器上

考虑到这两点,就会选用远程接口或本地接口

 

返回到刚才的HelloWorld java Project程序:

新建一个接口:

//继承HelloWorld的业务方法
public interface HelloWorldLocal extends HelloWorld{

}

 

修改实现的bean:

开发具有本地接口的无状态session <wbr>bean
让他既有本地接口,也有远程接口

优先调用本地接口

这样就可以使:当客户端与EJB在同一个JBOSS中,使用本地接口

客户端与EJB不在同一个JBOSS中,则使用远程接口

 

------------------------------------------------------------------

try{
   InitialContext cts = new InitialContext();
   HelloWorld helloWorld = (HelloWorld)cts.lookup("HelloWorldBean/remote");//使用远程接口
   System.out.println(helloWorld.getClass().getName()); //$Proxy3
   System.out.println(helloWorld.sayHello("明明")); //明明说:你好,世界!
  }catch(NamingException e){
   System.out.println(e.getMessage());
  }

EJB与客户端在同一个jboss中,也可用远程接口访问

------------------------------------------------------------------

<body>
    <%
     try{
   InitialContext cts = new InitialContext();
   HelloWorldLocal helloWorld = (HelloWorldLocal)cts.lookup("HelloWorldBean/local"); //使用本地接口
   out.println(helloWorld.getClass().getName()); //$Proxy3
   out.println(helloWorld.sayHello("本地人")); //本地人说:你好,世界!
  }catch(NamingException e){
   out.println(e.getMessage());
  }
     %>
  </body>

在Web客户端与EJB使用同一个jboss,可用本地接口

猜你喜欢

转载自leon-s-kennedy.iteye.com/blog/1537127