EJB中local跟remote的区别以及调用方法总结(转)

EJB中local和remote的区别以及调用方法总结(转)

local是本地接口,remote是远程接口。web层调用app层使用remote接口。session bean和entity bean之间调用使用的是local接口。不用说你也明白,remote接口对性能的影响很大。所以在程序设计的时候我们尽量用loacal接口,也就是facade模式。具体就是,web层调用app层的session bean,session bean在调用各个entity bean。就好比是打长途电话找5个人,你是准备给5个人分别通话(长途-remote)还是准备先和一人通话(长途-remote)然后在由这个人对另外4个(短途-local)分别通知?我想你会选择第二种情况(facade模式)。

local接口可以在与ejb同一个JVM环境中调用,但是不能对它进行远程调用,假设你的web容器与所需调用的ejb不在一台服务器上,或者不在同一个welogic server中时就不能调用local接口,在jndi查找的时候不能查找local home,而要查找remote home,也就是说需要实际进行RMI调用,而且必须提供Provider URL(例如t3://myserver:7001),而且他们返回给客户的对象也不一样,local home创建的是javax.ejb.EJBLocalObject类型,它没有继承Remote interface;而Remote home创建的是javax.ejb.EJBObject类型的,它扩展了Remote.实际上javax.ejb.EJBLocalObject型接口没有抛出RemoteException,因为对local类型接口的调用不是RMI,所以的对local接口的调用效率要高于对remote对象的调用,针对这点对EJB的设计提出以下建议:
1、如果你的ejb客户只可能存在于与ejb相同app server,或者说同一个JVM环境中时,你可以只生成local类型接口(包括EJBHome 与EJBObject),如果你需要在与EJB容器不同的JVM环境中调用你的EJB的话,你必须生成Remote类型的接口(包括EJBHome 与EJBObject);
2、在一般情况下建议两种类型的接口(包括EJBHome 与EJBObject)都生成,尤其是Session Bean,Entity Bean,可以只生成local类型的接口,如果想远程调用你的Entity Bean一般用Session Bean做代理。
3、如果你不是远程调用EJB的话,使用EJB时建议调用local接口,这样效率高,因为远程调用就意味着建立网络连接,效率必然不如local调用。
4、在jb7中设计EJB时,默认情况下只给你生成local类型接口,所以你需要在设计EJB时把interfaces设成:local/remote,这样的话你的EJB至少会有5个java文件

 

 

 

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

1、      客户端程序中调用EJB
前提:EJB要实现了REMOTE接口
客户端调用的代码可以用EJB Test Client工具生成。自己写就是这个样子:

 


       String url="t3://localhost:7001";
     Properties prop=new Properties();
     prop.put(Context.PROVIDER_URL,url);
            prop.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
            prop.put(Context.SECURITY_PRINCIPAL, "
name");
         prop.put(Context.SECURITY_CREDENTIALS,"
code");
     Context
context =new InitialContext(prop);
  
//通过ejbJNDI name查找到EJBHome对象
Object ref = context.lookup("
ejb/com/J2EE/first/ejb/HelloHome ");   
   //
得到EJBHome
HelloHome trH=(HelloHome) PortableRemoteObject.narrow(obj,HelloHome.class);
   //
得到EJBObject
    DigestSession digestSession = digestSessionHome.create();

   Hello tr=trH.create();
   System.out.println(tr.hello());

   byte[] ret = digestSession.md5(temp.getBytes());//ejb
方法调用

 

注意:Context.SECURITY_PRINCIPALContext.SECURITY_CREDENTIALS是可选的,涉及到对ejb的操作的权限。

 

2、SERVLET中调用EJB
前提:被调用的EJB实现了REMOTE接口
Servlet中,调用的代码应该是这个样子:

 


    try {
      Context context = new InitialContext();
      Object ref = context.lookup("UserFacade");
      //look up jndi name and cast to Home interface
      UserFacadeHome userFacadeHome = (UserFacadeHome) PortableRemoteObject.
          narrow(ref, UserFacadeHome.class);
      UserFacade userFacade = userFacadeHome.create();
      userFacade.updateUser("002","
老二");    }
    catch (Exception ex) {
      ex.printStackTrace();
    }

 


跟客户端程序中调用EJB的差别是在Context的生成上,servlet中直接用
Context context = new InitialContext();
而客户端程序中是用
    Properties properties = new Properties();
    properties.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
    properties.put(Context.PROVIDER_URL, "t3://localhost:7001");

 

    Context context= new InitialContext(properties);

 

3、      EJB中调用其他的EJB(同一EJB模块)
前提:
(1)
被调用者实现了LOCAL接口,调用者则实现了REMOTE接口
(2)
调用者和被调用者应该在同一EJB模块打包文件(jar)
(3)
调用者的部署描述(ejb-jar.xml)中有关于Local ref的描述,如下所示:

 


    <session>
      <display-name>UserFacade</display-name>
      <ejb-name>UserFacade</ejb-name>
      <home>ejbtest.test.UserFacadeHome</home>
      <remote>ejbtest.test.UserFacade</remote>
      <ejb-class>ejbtest.test.UserFacadeBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>
      <ejb-local-ref>
        <ejb-ref-name>ejb/user</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <local-home>ejbtest.test.UserHome</local-home>
        <local>ejbtest.test.User</local>
        <ejb-link>User</ejb-link>
      </ejb-local-ref>
    </session>

在调用者中,调用的程序代码应该是下面的样子:

 

package ejbtest.test;import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.ejb.CreateException;

 

import javax.ejb.*;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.rmi.RemoteException;

 

public class UserFacadeBean
    implements SessionBean {
SessionContext sessionContext;
private UserHome userHome;
private static Context context;

 

public void ejbCreate() throws CreateException {
}

 

public void ejbRemove() {
}

 

public void ejbActivate() {
}

 

public void ejbPassivate() {
}

 

public void setSessionContext(SessionContext sessionContext) {
    System.out.println("@@@@@@@@@@@@@@@@ UserFacadeBean.setSessionContext()");
    this.sessionContext = sessionContext;
    try {
      findUserHome();
    }
    catch (Exception e) {
      throw new EJBException(e.getMessage());
    }
}

 

private void findUserHome() throws Exception {
    final String ENTITY_NAME = "java:comp/env/ejb/user";

 

    context = new InitialContext();

 

    if (userHome == null) {
      try {
        Object object = context.lookup(ENTITY_NAME);
        userHome = (UserHome) object;
      }
      catch (Exception e) {
        throw new EJBException(e.getMessage());
      }
    }
}

 

public void addUser(String id, String name) throws RemoteException {
    try {
      User user = userHome.create(id);
      user.setName(name);
    }
    catch (Exception ex) {
      throw new RemoteException(ex.getMessage());
    }
}
}

 

4EJB中调用其他的EJB(不同的EJB模块)
前提:被调用者实现了REMOTE接口
最简单的方法是按客户端程序(或者SERVLET)中调用EJB的方法。