YCOE

You Can't stOp mE!

导航

EJB入门

Posted on 2006-04-11 01:17  YCOE  阅读(2006)  评论(0编辑  收藏  举报

  EJB,一个高层次的框架,总让人觉得神秘莫测.但其实它的实现却出乎意料的简单.表面上看,它只是把Bean从不同的机上分离出去而已.其实我们也不用去理太多它的内部实现,至少在入门阶段是这样的.呵呵.下面开始啦:

参考资料:http://www.soft6.com/know/detail.asp?id=BAIEFJ
                    <<Mastering Enterprise JavaBeans  Third Edition >>By Ed Roman

本例代码是在WebLogic 8.1 的例题改编:
D:\bea\weblogic81\samples\server\examples\src\examples\webservices\basic\statelessSession,由于文档的注释与改编后有出入,这里把全部的注释删除,另在代码外进行说明.
                    

        JBoss和JDK的安装这里就不再重复了,不懂的话自己到网上找下.

        Hello.java
        这是一个远程接口,支持EJB组件暴露的所有业务方法,在客户同EJB对象互交时,需要使用这一接口,窗口厂商会实现这一接口,而相应的实现对象就是EJB对象.EJB对象会将客户请求委派给实际的EJB Bean类.此类必需抛出RemoteException异常.

package com.ycoe.ejb;

import java.rmi.RemoteException;
import javax.ejb.EJBObject;

public interface Hello extends EJBObject {

  String sayHello(String name) 
throws RemoteException;
}


        HelloLocal.java
        Hello EJB组件的本地接口,当酵客户同EJB酵对象互交时,需要使用这一接口.而相应的实现对象就是EJB本地对象.EJB本地对象会将客户请求委派给实际的EJB Bean类.由于是本地接口,所以不需要抛出RemoteException异常.
package com.ycoe.ejb; 


import javax.ejb.EJBLocalObject;

public interface HelloLocal extends EJBLocalObject

    
public String hello();
}
 

        HelloLocalHome.java
        本地Home接口是Home接口的高性能版本.它由EJB服务器提供的工具实现,本地Home接口实现称之为本地Home对象,本地Home对象充当了创建EJB本地对象的工厂.本地Home对象并不是远程对象,因此不必抛出远程异常.
package com.ycoe.ejb; 

import javax.ejb.CreateException;
import javax.ejb.EJBLocalHome;

public interface HelloLocalHome extends EJBLocalHome

    HelloLocal create() 
throws CreateException;
}
 
 
       HelloHome.java
        为了创建和销毁EJB对象,开发者需要使用Home接口.Home对象由EJB服务器提供的工具生成.Home对象充当了创建EJB对象的工厂.
        create方法还能完成EJB组件的初始化工作,由于EJBHome定义了用于销毁EJB对象的方法,因此HelloHome不用再定义它.
package com.ycoe.ejb;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;


public interface HelloHome extends EJBHome {

  Hello create()
    
throws CreateException, RemoteException;

}


  HelloBean.java
        这是一个无状态的会话Bean.,当初始化和销毁企业Bean实例时,容器将同它互交,但客户并不需要使用这些回调方法.因此在客户代码中绝对看不到它们的调用,因为公公有EJB容器使用它们.HelloBean类存在ejbCreate()方法,同Home对象的create()方法一致.会话Bean不会用到ejbActivate()(激活)和ejbPassivate()(挂起)操作(在有状态Bean中使用!),因此这两个方法为空.
package com.ycoe.ejb;

import javax.ejb.CreateException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class HelloBean implements SessionBean {

  
private static final boolean VERBOSE = true;
  
private SessionContext ctx;

  private void log(String s) {
    
if (VERBOSE) System.out.println(s);
  }
 
  

  
public void ejbActivate() {
    log(
"ejbActivate called");
  }


  
public void ejbRemove() {
    log(
"HelloBean.ejbRemove()");
  }


  
public void ejbPassivate() {
    log(
"HelloBean.ejbPassivate()");
  }


  
public void setSessionContext(SessionContext ctx) {
    log(
"HelloBean.setSessionContext()");
    
this.ctx = ctx;
  }


  
public void ejbCreate () throws CreateException {
    log(
"HelloBean.ejbCreate()");
  }

  

  
public String sayHello(String inputStr) {
    String retStr 
= "Run from Jboss:"+ inputStr ;
    log(retStr);
    
return retStr;
  }

}


  到此全部编码已经完成了,接下来是布署.
        首先要写个布署文件,如果用Jbuilder的话可以自动生成.如下:
        1.创建一个META-INF文件夹,在此文件夹下面建一个ejb-jar.xml布署文件
        2.编写布署文件,内容如下:
       
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="2.1" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd"
> 
  
<enterprise-beans>
    
<session>        
      
<ejb-name>Hello</ejb-name>
        
      
<home>com.ycoe.ejb.HelloHome</home>
        
      
<remote>com.ycoe.ejb.Hello</remote>
        
      
<ejb-class>com.ycoe.ejb.HelloBean</ejb-class>
        
      
<session-type>Stateless</session-type>
        
      
<transaction-type>Bean</transaction-type>
       
    
</session>
  
</enterprise-beans>
</ejb-jar>

这个简单
<ejb-name>:企业Bean的昵称.在部署描述符的其他地方能够引用它,供设置其他参数使用
<home>:Home接口的全限定名(包名也要带上)
<remote>:远程接口的全限定名
<local-home>:本地Home接口的全限定名
<local>:本地接口的全限定名
<ejb-class>:企业Bean类的全限定名
<session-type>:标识企业Bean是有状态的还是无状态的
<transaction-type>:事务

不同的容器可能还要其它的布署文件,具体看容器的说明.

      到这里,EJB的所有东西都做好了.剩下打包了.
3.在DOS窗口下进入此文件的目录.以本例为例,进入D:\Eclipse\Hello目录结构如下:
         Hello
            |_META-INF
            |   |_ejb-jar.xml
            |_com
                |_ycoe
                    |_ejb
                        |_Hello.java
                        |_HelloBean.java
                        |_HelloHome.java
                        |_HelloLocal.java
                        |_HelloLocalHome.java
            在命令行输入:jar cf Hello.jar com META-INF
            各参数作用这里不再说明,上网找吧,到处都是.
            这时可以看到在Hello目录下又多了一个Hello.jar文件,这就是我们要的!
4.布署Jar文件.这一步在JBoss下面非常容易.启动JBoss后,把Hello.jar文件复制到%JBOSS_DIST%\server\default\deploy目录下(%JBOSS_DIST%为JBoss安装目录)
             可以看到JBoss的输出信息:
             SP1/server/default/deploy/Hello.jar
             22:16:58,937 INFO  [EjbModule] Deploying Hello
              22:16:59,546 INFO  [ProxyFactory] Bound EJB Home 'Hello' to jndi 'Hello'
              22:16:59,546 INFO  [EJBDeployer] Deployed: file:/C:/Program Files/jboss-4.0.3SP1/server/default/deploy/Hello.jar
             可以看到JAR文件热布署成功!
5.编写测试代码:

        Client.java
        要调用EJB中的接口,必需先初始化上下文环境.这里由一个专门的方法private static Context getInitialContext() throws NamingException来实现.这是由Jbuilder生成的初始化方法.即使不在本地的EJB服务器,只要更改这里的put(...)里面的路径就可以直接访问到.不同的容器这部分有所区别,具体可以参照容易的API.这里我们使用的是JBoss服务器.这个类中,我们使用了键盘输入与EJB互交的示例,而不是简单的打印而已,可以更好的理解EJB的存在.为了理解EJB的作用,建议再装一个JDK,不同版本的也没关系.在另一个JDK中运行这个程序,或者干脆用另一台电脑,但注意此时要修改下面的初始化上下文环境代码.这里不再多说
package com.ycoe.ejb;

import java.io.InputStream;
import java.util.Hashtable;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;


public final class Client {

    
  
public Client() {}

public static void main(String[] argv)
    
throws Exception
  
{
    Properties props 
= System.getProperties();
    Context context = getInitialContext();
    Object ref 
= context.lookup("Hello");
    HelloHome helloHome = (HelloHome) PortableRemoteObject.narrow(ref, HelloHome.class);
    Hello hello 
= helloHome.create();

    InputStream input 
= System.in;
    
byte[] inputBytes = new byte[255];
    
int count = 0;
    String strInput 
= "";
    
while (!"exit".equalsIgnoreCase(strInput)) {
        
try{
            count 
= input.read(inputBytes);
        }
catch(Exception ex){}
        strInput 
= new String(inputBytes, 0, count);
        System.out.println(
"This is run from client:"+strInput);
        hello.sayHello(strInput);
    }

    hello.remove();
  }

  
  
private static Context getInitialContext() throws NamingException {
      Hashtable environment 
= new Hashtable();

      environment.put(Context.INITIAL_CONTEXT_FACTORY,
                      
"org.jnp.interfaces.NamingContextFactory");
      environment.put(Context.URL_PKG_PREFIXES,
                      
"org.jboss.naming:org.jnp.interfaces");
      environment.put(Context.PROVIDER_URL, 
"jnp://localhost:1099");

      
return new InitialContext(environment);
  }

}


测试结果:
    编译运行com.ycoe.ejb.Client 从键盘上输入几个字符,回车,可以看到在Client端输出:
         hello
         This is run from client:hello

         sdf
         This is run from client:sdf

         exit
         This is run from client:exit

     在JBoss端输出:
         23:24:22,593 INFO  [STDOUT] HelloBean.setSessionContext()
         23:24:22,703 INFO  [STDOUT] HelloBean.ejbCreate()
         23:24:25,562 INFO  [STDOUT] Run from Jboss:hello
         23:24:31,046 INFO  [STDOUT] Run from Jboss:sdf
         23:44:58,250 INFO  [STDOUT] Run from Jboss:exit

    到这里,全部内容已经完成!祝你好运!

                                                            --原创文章,可以任意复制发表,但请注明作者与出处,尊重版权!
                                                                                                                       BY YCOE