开发EJB

 1 、类介绍:

  开发EJB的主要步骤一般来说,整个的开发步骤(开发,配置,组装)包括如下几个方面。开发:首先要定义三个类:Bean类本身,Bean的本地和远程接口类。 配置:配置包括产生配置描述器--这是一个XML文件、声明了Enterprise Bean的属性、绑定了bean的class文件(包括stub文件和skeleton文件)。最后将这些配置都放到一个jar文件中。还需要在配置器中定义环境属性。组装应用程序:包括将Enterprise beans安装到Server服务器中,测试各层的连接情况。程序组装器将若干个Enterprise Beans与其它的组件结合起来。组合成一个完整的应用程序。或者将若干个Enterprise beans组合成一个复杂的Enterprise Bean管理Enterprise Bean。 
  
我们必须定义和编写一些EJB中的基本类。如Enterprise bean类:这是Enterprise bean内部应用逻辑的实现。编写Enterprise bean的远程接口类。编写Enterprise bean的本地接口类。说明主键类,主键类只是对于Entity bean才需要的。在Enterprise bean的配置描述器中指定主键的名字。Enterprise beans提供者定义了远程接口和本地接口,实现了EJB类本身。Remote接口中提供了客户调用EJB实现的应用逻辑函数的接口。而home接口提供了产生和定位remote接口实例的方法。  

  在Enterprise bean本身类的实现,本地home接口,远程remote接口之间并没有正式的联系(例如继承关系)。但是,在三个类里声明的方法却必须遵守EJB里面定义的规范。例如: 你在Enterprise bean里面声明了一个应用程序的方法或者说应用逻辑。也在beansremote接口中声明了这个方法,那么,这两个地方必须要同样的名字。Bean的实现里面必须至少有一个Create()方法:ejbCreate()。但是可以有多个带有不同参数的create()方法。

  在home接口中,也必须有相同的方法定义(参数的个数相同)。EjbCreate()方法返回的一个容器管理的持久对象。它们都返回一个容器管理持久性的主键值。但是,在home的相应的Create()方法中返回值的类型是remote接口。

  注意:实体bean的实现的ejbCreate方法有点不同。实体bean可以不定义ejbCreate方法。如果实体只是通过应用程序或通过数据库管理程序的途径被加到数据库中,实体bean就省略了ejbCreate方法。EjbCreate返回的值是主键类型。如果ejbCreate方法是容器管理持久性的实体bean的方法,它的返回值就是NULL类型。如果实体bean实现了Bean管理的持久性,ejbCreate方法就返回值类型就是主键类型。容器的任务是把各接口和Enterprise bean的实现类结合起来。保证在编译时和运行时,各接口和实现类是相对应的。  

EJB的实现类,各接口要从不同的基类中继承下来。一个会话bean必须实现基类javax.ejb.SessionBean。而实体bean必须实现基类javax.ejb.EntiyBean。这些EJB的基类都是从javax.ejb.EnterpriseBean继承而来。而javax.ejb.EnterpriseBean又是从java.io.Serializable继承而来。每一个Enterprise Bean都必须有一个remote接口。Remote接口定义了应用程序规定客户可以调用的逻辑操作。这些是一些可以由客户调用的公共的方法,通常由Enterprise beans类来实现。注意,Enterprise bean的客户并不直接访问Bean。而是通过remote接口来访问。Enterprise bean类的remote接口扩展了javax.ejb.EJBObject类的公共java接口。而Javax.ejb.EJBObject是所有remote接口的基类。其代码如下:  

package javax.ejb 
public interface EJBObject extends java.rmi.Remote{ 
public EJBHome getEJBHome
() throws java.rmi.RemoteException 
public Object getPrimaryKey
() throws java.rmi.RemoteException 
public void Remove
() throws java.rmi.RemtoeException, java.rmi.RemoveException 
public Handle getHandle
() throws java.rmi.RemoteException
boolean isIdentical 
EJBObject p0 throws java.rmi.RemoteException 
}   

getEJBHome()方法允许你取得一个相关的Home接口。对于 实体Bean,用getPrimaryKey()方法获得实体Bean的主键值。Remove()可以删除一个Enterprise bean。具体的语义在各种不同类型的enterprise beans的生命周期中,由上下文中解释的。方法getHandle()返回了一个Enterprise bean实例的持久的句柄。IsIndentical()方法允许你去比较Enterprise beans是否相同。

2、方法:

  所有的remote接口中的方法必须声明为公共(public)的,并必须抛出java.rmi.RemotException异常。另外,所有的remote接口中的方法定义的参数和都必须是在RMI-IIOP中有效的。对每一个在remote接口中定义的方法,在Enterprise bean 类里面都要有相应的方法。相应的方法必须要有同样的名字,同样类型和数量的参数,同样的返回值,而且还要抛出同样的例外。 如下代码显示了一个ATM例子的会话bean的remote接口Atm,。里面声明了一个应用方法transfer()。黑体部分表示EJB规范中必须要有的内容。Remote接口必须扩展javax.ejb.EJBObject类。从客户端调用的Enterprise bean的每一个方法都必须在remote接口中声明。Transfer()方法抛出了两个意外。其中InSufficientFundsException例外是应用程序定义的意外。 


Public interface Atm extends javax.ejb.EJBObject{ 
Public void transfer(String Source, String Target, float amount)
Throws java.rmi.RemoteException, InSufficientFundsException; 
}   

Home接口必须定义一个或多个的Create()方法。每一个这样的Create()方法都必须命名为Create。并且,它的参数,不管是类型还是数量都必须与bean类里面的ejbCreate()方法对应。注意,home接口中的Create()方法和bean类中ejbCreate()方法的返回值类型是不同的。实体beanhome接口还包含find()方法。 每一个Home接口都扩展了javax.ejb.EJBHome接口。如下代码显示了javax.ejb.EJBHome接口的定义:  

package javax.ejb; 
public interface EJBHome extends java.rmi.Remote() { 
void remove(Handle handle) throws java.rmi.RemoteException,RemoveException; 
void remove(Object primarykey) throws java.rmi.RemoteException,RemoveException; 
EJBMetaData getEJBMetaData() throws RemoteException; 
Homehandle getHomeHandle() throws RemoteException; 
}  

  这里提供了两个remove()方法来删除Enterprise bean的实例。第一个remove方法是通过句柄来删除一个Enterprise bean的实例。第二个remove方法通过主键来删除一个Enterprise bean的实例。 在众多的Enterprise bean实例中,句柄唯一的标识一个实例。一个句柄与它引用的Enterprise bean有相同的生命期。考虑一个实体对象,客户可以通过一个句柄来重新获得相应的Enterprise bean的实例。一个句柄能够对应一个Enterprise bean对象的多个实例。例如,即使当Enterprise bean对象所在的主机崩溃了,或者Enterprise bean对象在不同的机器之间移动,句柄仍是有效的。这里的句柄是Serialized句柄,与CORBA中的字符串化的CORBA对象的引用是相似的概念。在EJBHome接口中的第二个remove操作通过其主键来决定要删除的Enterprise bean。主键可以是扩展了Java Object类的任何类型,但是,必须要实现Java的Serializable接口。主键是标识实体bean的主要的方法。通常,主键是数据库中的一个关键字,唯一的定义了由实体bean代表的数据。  

  方法getEJBMetaData()返回了Enterprise bean对象的metadata接口。这个接口允许客户获得Enterprise beanmetadata信息。当开发工具来编译链接应用程序的时候,或者配置工具来配置的时候,可能会用到metadata信息。Javax.ejb.EJBMetadata接口提供了获得javax.ejb.EJBHome接口,home类,remote接口,还有获得主键的方法。也提供了一个isSesson()的方法来确定在放这个home接口的对象是会话bean还是实体bean

IsStatelessSession()方法指示这个会话bean是有状态还是无状态的。如下代码显示了javax.ejb.EJBMetadata接口的定义部分的代码。

Public javax.ejb Public interface EJBMetaData{ 
EJBHome getEJBHome
();
Class getHomeInterfaceClass
(); 
Class getRemoteInterfaceClasss
();
Class getPrimaryKeyClass
(); 
Boolean isSession
();
Boolean isStatelesssSession
(); 
}   

  对每一个Create()方法,EJB规范定义了如下的命名约定。它的返回值是会话beanremote接口的类型。方法的名字只能是Create()。对会话bean类中的每一个ejbCreate()方法都必须有一个Create()与之对应。 对于每一个Create()方法的参数的类型和数量都必须与会话bean类中的ejbCreate()方法相对应。方法必须抛出java.rmi.RemoteException例外。 方法必须抛出javax.rmi.CreateExeption例外。 Create()方法的参数是用来初始化新的会话bean对象的。 如下代码显示了一个会话bean对象的不同的Create()方法,其中必须的部分用粗体显示:  

public interface AtmHome extends javax.ejb.EJBHome{ 
Atm create() throws java.rmi.RemoteException,javax.ejb.CreateException; 
Atm create(Profile preferredProfile) 
Throws java.rmi.RemoteExeption,javax.ehrows java.rmi.RemoteException,RemoveException; 
EJBMetaData getEJBMetaData() throws RemoteException; 
Homehandle getHomeHandle() throws RemoteException; 
}  

  这里提供了两个remove()方法来删除Enterprise bean的实例。第一个remove方法是通过句柄来删除一个Enterprise bean的实例。第二个remove方法通过主键来删除一个Enterprise bean的实例。在众多的Enterprise bean实例中,句柄唯一的标识一个实例。一个句柄与它引用的Enterprise bean有相同的生命期。考虑一个实体对象,客户可以通过一个句柄来重新获得相应的Enterprise bean的实例。一个句柄能够对应一个Enterprise bean对象的多个实例。例如,即使当Enterprise bean对象所在的主机崩溃了,或者Enterprise bean对象在不同的机器之间移动,句柄仍是有效的。这里的句柄是Serialized句柄,与CORBA中的字符串化的CORBA对象的引用是相似的概念。  

  在EJBHome接口中的第二个remove操作通过其主键来决定要删除的Enterprise bean。主键可以是扩展了Java Object类的任何类型,但是,必须要实现Java的Serializable接口。主键是标识实体bean的主要的方法。通常,主键是数据库中的一个关键字,唯一的定义了由实体bean代表的数据。方法getEJBMetaData()返回了Enterprise bean对象的metadata接口。这个接口允许客户获得Enterprise beanmetadata信息。当开发工具来编译链接应用程序的时候,或者配置工具来配置的时候,可能会用到metadata信息。Javax.ejb.EJBMetadata接口提供了获得javax.ejb.EJBHome接口,home类,remote接口,还有获得主键的方法。也提供了一个isSesson()的方法来确定在放这个home接口的对象是会话bean还是实体beanIsStatelessSession()方法指示这个会话bean是有状态还是无状态的。如下代码显示了javax.ejb.EJBMetadata接口的定义部分的代码。

Public javax.ejb 
Public interface EJBMetaData{ 
EJBHome getEJBHome
(); 
Class getHomeInterfaceClass
();
Class getRemoteInterfaceClasss
(); 
Class getPrimaryKeyClass
(); 
Boolean isSession
(); 
Boolean isStatelesssSession
(); 
}  

五、EJB的编程环境:

1 使用Jbuilder 

JbuilderEJB Container能够进行无缝连接。JbuilderInprise的应用服务器包括了所有的开发和配置Enterprise Beans的工具以及所需要的库:运行和管理Enterprise Bean的容器、命名服务、 事务服务、Java数据库、开发Enterprise Beans所需要的API、一个增强的java-to-iiop编译器,支持值类型和RMI信号等等。  

Jbuilder还提供了一个快速开发应用程序Enterprise Beans的工具和向导。通过简单而且直观的步骤,向导帮助你建立一个Enterprise Bean。自己设定某些缺省值,产生了bean的模板,在上面,我们可以增加我们自己的应用逻辑。Jbuilder也提供了一个EJB的接口生成向导。向导在Enterprise Bean的公共方法基础上生成了Remote接口和Home接口。Jbuilder还提供一个配置器的向导帮助我们逐步的建立XML描述器文件。并将生成的Stubs集中到一个jar文件中。

2、使用Jbuilder之外的集成环境:  

  如果你使用其它的除了别的集成环境(IDE)。要确定使用了集成环境IDE所带的容器工具。也要验证IDE是否支持EJB规范的相应的版本,还要确定它是否正确的支持EJBAPI  

  要确定JD到所支持的EJB容器的版本。可以通过检查Inprise的安装说明来确定EJB容器所支持的支持JDK的版本。  

  在配置Enterprise Bean的时候,你必须使用Inprise的应用服务器所提供的工具。这些工具能够编辑和修改第三方的代理商提供的Inprise配置描述器。还能够验证配置描述器,能够验证bean的源代码。  

  六、一个简单的HELLO例子  

1、安装Apusic Application Server  

Note:以下以Linux为例,来说明Apusic Application Server的安装过程。其他平台的安装,可参考Apusic Application Server安装手册。  

  下载JDK1.2Apusic Application Server必须运行在JDK1.2以上环境中。可从以下站点下载最新JDK 
http://java.sun.com  

  下载Apusic Application Server
Apusic Application Server 
试用版可从以下网址得到: 
http://www.apusic.com/download/enter.jsp  

  在下载完成后,你可以得到一个包裹文件apusic.zip,选定安装目录,假设安装到/usr下,则用以下命令:  


cd /usr
jar xvf apusic.zip 
/usr下会出现一个目录apusic,Apusic Application Server的所有程序都被解压到/usr/apusic下。 
将以下路径加入到CLASSPATH中 
/usr/apusic/lib/apusic.jar
$JAVA_HOME/lib/tools.jar   

  用以下命令运行Apusic Application Server  

  java -Xms64m com.apusic.server.Main -root /usr/apusic  

  2、定义EJB远程接口(Remote Interface) 

  任何一个EJB都是通过Remote Interface被调用,EJB开发者首先要在Remote Interface中定义这个EJB可以被外界调用的所有方法。执行Remote Interface的类由EJB生成工具生成 

  以下是HelloBean的Remote Inteface程序:  

package ejb.hello; 

import java.rmi.RemoteException;
import java.rmi.Remote;
import javax.ejb.*; 

public interface Hello extends EJBObject, Remote { 

//this method just get "Hello World" from HelloBean.
public String getHello() throws RemoteException;
}
  

  3、定义Home Interface 

  EJB容器通过EJB的Home Interface来创建EJB实例,和Remote Interface一样,执行Home Interface的类由EJB生成工具生成。  

  以下是HelloBean 的Home Interface程序: 

package ejb.hello;  

import javax.ejb.*;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.*; 

/**
* This interface is extremely simple it declares only
* one create method.
*/
public interface HelloHome extends EJBHome { 

public Hello create() throws CreateException, 
RemoteException; 

}
  

4、写EJB

  在EJB类中,编程者必须给出在Remote Interface中定义的远程方法的具体实现。EJB类中还包括一些 EJB规范中定义的必须实现的方法,这些方法都有比较统一的实现模版,编程者只需花费精力在具体业务方法的实现上。  

  以下是HelloBean的代码:


package ejb.hello

import javax.ejb.*
import java.util.*

import java.rmi.*

public class HelloBean implements SessionBean {
static final boolean verbose = true

private transient SessionContext ctx; 

// Implement the methods in the SessionBean
// interface
public void ejbActivate() {
if (verbose)
System.out.println("ejbActivate called");

public void ejbRemove() {
if (verbose)
System.out.println("ejbRemove called");

public void ejbPassivate() {
if (verbose)
System.out.println("ejbPassivate called");

/**
* Sets the session context.
*
* @param SessionContext
*/
public void setSessionContext(SessionContext ctx) { 
if (verbose)
System.out.println("setSessionContext called");
this.ctx = ctx;

/**
* This method corresponds to the create method in
* the home interface HelloHome.java. 
* The parameter sets of the two methods are 
* identical. When the client calls 
* HelloHome.create(), the container allocates an 
* instance of the EJBean and calls ejbCreate(). 
*/ 
public void ejbCreate () {
if (verbose)
System.out.println("ejbCreate called");
}
/**
* **** HERE IS THE BUSINESS LOGIC *****
* the getHello just return a "Hello World" string.
*/
public String getHello()
throws RemoteException
{
return("Hello World");
}
}
  

  5、创建ejb-jar.xml文件 

  ejb-jar.xml文件是EJB的部署描述文件,包含EJB的各种配置信息,如是有状态Bean(Stateful Bean) 还是无状态Bean(Stateless Bean),交易类型等。ejb-jar.xml文件的详细信息请参阅EJB规范。以下是HelloBean的配置文件:

<?xml version="1.0"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems Inc.//DTD Enterprise JavaBeans 1.2//EN" "http://java.sun.com/j2ee/dtds/ejb-jar_1_2.dtd";>
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>Hello</ejb-name>
<home>ejb.hello.HelloHome</home>
<remote>ejb.hello.Hello</remote>
<ejb-class>ejb.hello.HelloBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session> 
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>Hello</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction> 
</assembly-descriptor>
</ejb-jar>  

6、编译和部署

  编译Java源文件并将编译后classejb-jar.xml打包到Hello.jar  

mkdir build
mkdir build/META-INF
cp ejb-jar.xml build/META-INF
javac -d build *.java
cd build
jar cvf Hello.jar META-INF ejb
cd ..   

  用EJB工具生成可部署到Apusic Application Server中运行的jar文件:  

java com.apusic.ejb.utils.EJBGen -d /usr/apusic/classes/Hello.jar build/Hello.jar  

增加/usr/apusic/classes/Hello.jar到CLASSPATH中  

  将Hello.jar加入到Apusic Application Server配置文件中。在/usr/apusic/config/server.xml 加入以下几行:  

<module>
<ejb>
<ejb-uri>classes/Hello.jar</ejb-uri>
<bean>
<ejb-name>Hello</ejb-name>
<jndi-name>HelloHome</jndi-name>
</bean>
</ejb>
</module>  

启动服务器  

java -Xms64m com.apusic.server.Main -root /usr/apusic 

7、写客户端调用程序

  您可以从Java ClientJSPServlet或别的EJB调用HelloBean 
  调用EJB有以下几个步骤: 
  通过JNDIJava Naming Directory Interface)得到EJB Home Interface 
  通过EJB Home Interface 创建EJB对象,并得到其Remote Interface 
  通过Remote Interface调用EJB方法  

  以下是一个从Java Client中调用HelloBean的例子:


package ejb.hello

import javax.naming.Context

import javax.naming.InitialContext

import java.util.Hashtable

import javax.ejb.*

import java.rmi.RemoteException

/**
* @author Copyright (c) 2000 by Apusic, Inc. All Rights Reserved.
*/
public class HelloClient{
public static void main(String args[]){
String url = "rmi://localhost:6888";
Context initCtx = null;
HelloHome hellohome = null;
try{
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.apusic.jndi.InitialContextFactory"); 
env.put(Context.PROVIDER_URL, url); 
initCtx = new InitialContext(env);
}catch(Exception e){
System.out.println("Cannot get initial context: " + e.getMessage());
System.exit(1);
}
try{
hellohome = (HelloHome)initCtx.lookup("HelloHome"); 
Hello hello = hellohome.create();
String s = hello.getHello();
System.out.println(s); 
}catch(Exception e){
System.out.println(e.getMessage());
System.exit(1);

}
  

  运行HelloClient,可得到以下输出: 

  Hello World  

EJB(Enterprise JavaBeans)可不算什么新概念了,但许多人在听到或者看到这个名词的时候还会眼晕。EJB组件在J2EE规范中自成一层,把应用程序的表示层和后端信息系统(比如数据库或者主框架计算机)捆绑了起来。EJB架构既用到了EJB对象的功能又利用了它们所运行的环境。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值