J2EE全实例教程2

发表于:2007-06-21来源:作者:点击数: 标签:
J2EE全实例教程2 第2章 快速上手 企业Bean(Enterprise Java Bean,EJB)在J2EE应用中处于核心地位。EJB程序的 开发 是实现J2EE倡导的分布式企业级组件应用的重要组成部分。按照EJB模式开发的应用程序在大型电子商务(e-Commerce)、企业应用集成(Enterprise A

   
J2EE全实例教程2


第2章 快速上手

  企业Bean(Enterprise JavaBean,EJB)在J2EE应用中处于核心地位。EJB程序的开发是实现J2EE倡导的分布式企业级组件应用的重要组成部分。按照EJB模式开发的应用程序在大型电子商务(e-Commerce)、企业应用集成(Enterprise Application Integration,EAI)等方面表现出无可比拟的优势,目前已被多家大型IT厂商支持,成为最广泛的分布式组件应用规范。
  EJB应用的基本模式是容器/组件应用模式。容器对应EJB服务器或应用服务器,如Weblogic Server等;组件就是EJB程序。对开发者来说,只关注与业务逻辑相关的组件程序,而不必管分布式应用带来的并发、大量事务完整性等问题,从而使开发分布应用不必再跨越很高的门槛,使其简单可行。
  无论哪种类型的EJB应用程序,它们的开发步骤都是类似的。掌握了一个简单EJB的开发过程,就可以进一步开发更加复杂的应用。本章假设读者从来没有开发过EJB,也不具备EJB的任何知识而准备以最简捷的方式开发出一个简单的EJB应用。
  在本章开发一个简单的EJB之前,假设读者已安装了WebLogic Server 6.0sp2。关于WebLogic Server 6.0的安装和简单介绍,请看第1章。
  本章的简单实例的名字叫HelloWorldEJB。它只有一个简单的方法sayHello,用来模拟业务逻辑。客户端调用这个方法,获取字符串并显示出来。更复杂情形的实例会在后面几章给出。好,准备你的EJB之旅吧!

2.1 准备工作

  其实并没有太多的准备工作要做,但为了保持整洁、有序、清晰的工作环境,做一些简单的准备还是很有必要的。

2.1.1 确定工作目录

  为了本书叙述方便,这里为读者指定了一个存放源程序的目录,可以把它叫做工作目录,工作目录确定为c:work,读者当然可以选用其它的目录(如有些人认为把C盘作为工作目录不好,而把工作目录建在D盘),如果这样,就要做好与作者叙述的映射工作,以免出现问题。

2.1.2 编写环境变量脚本

  开发Java程序过程中,环境变量是程序员要管理的一件事。这些环境变量包括系统环境变量,如path、classpath和用户定义的环境变量。当环境变量较少时,可以直接把它们设置成系统级的,但如果环境变量较多,就不适宜把它们都设成系统级的,这时用一个脚本程序来设置这些环境变量是个很的选择。
  在本书中用到的所有实例的环境变量,包括系统级的和用户级的,都用一个环境变量脚本程序来设置。在具体使用的时候,无论是编译,还是执行,只要先运行一下这个脚本命令即可。
  这个脚本命令名为setEnv.cmd,放在C:work目录下,可以在命令窗口(有人习惯称为DOS窗口或控制台窗口)的任何路径下运行,运行命令如下:
  c:worksetEnv.cmd
  读者可以从配套光盘的work路径下找到setEnv.cmd,把它拷贝到C:work。也可以用文本编辑器编写,以setEnv.cmd的名字保存到路径C:work下。其代码如下:

rem 设置系统信息
set JAVA_HOME=C:eajdk130
set WL_HOME=c:eawlserver6.0
set DOMAIN_NAME=mydomain

rem 以下不用修改
set path=%path%;%JAVA_HOME%in
set classpath=.;%classpath%;%WL_HOME%libweblogic.jar
set EX_WEBAPP_CLASSES=%WL_HOME%config\%DOMAIN_NAME%applicationsDefaultWebApp_myserverWEB-INFclasses
set CLIENT_CLASSES=%WL_HOME%config\%DOMAIN_NAME%clientclasses
set SERVER_CLASSES=%WL_HOME%config\%DOMAIN_NAME%serverclasses
set classpath=%classpath%;%CLIENT_CLASSES%;%SERVER_CLASSES%
set Classpath=%classpath%;%JAVA_HOME%lib ools.jar


2.1.3 文本编辑器

  为编写EJB程序代码和部署代码,需要一个文本编辑器。可以使用Windows自带的“记事本(NotePad)”编辑器。但建议选择功能强一些的文本编辑器,如UltraEdit,EditPlus等。
  准备工作先做到这里,下面就进行第一个EJB的开发了。

2.2 EJB开发

  在开发这个HelloWorleEJB之前,首先在工作目录C:work中为这个实例创建一个子目录。本章的实例目录是C:workhello。
  如图2-1所示的EJB应用开发过程图。这个图是笔者多年开发经验的结晶,希望聪明的读者不要错过。EJB开发基本上都遵循这个过程,从总体上说,可以分成 五个步骤:
  (1)EJB程序代码编写
  (2)EJB程序代码编译
  (3)EJB部署描述文件编写
  (4)打包
  (5)编译生成容器代码
  每个步骤使用的工具不同,生成相应的阶段产品。关于开发过程的理解和掌握读者随着后面讨论的深入逐渐加深。


图2-1 EJB开发过程示意图

2.2.1 EJB代码编写

  HelloWorld EJB程序代码包括的接口和类名,如表2-1所示。

        表2-1 HelloWorld EJB程序文件说明
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   接口或类名  类型  文件名  功能  所在路径
  ───────────────────────────────
  HelloHome 主接口 HelloHome.java 定义创建方法 c:workhello
  Hello 远程接口 Hello.java 定义业务逻辑方法 c:workhello
  HelloBean Bean类 HelloBean.java 实现业务逻辑 c:workhello
  HelloClient客户端类 HelloClientjava 测试程序 c:workhello
  ───────────────────────────────
  1.编写主接口程序
  在文本编辑器中编辑HelloHome.java文件,并保存在C:workhello目录下,其代码为:

  //本接口需要引入的类或接口
  import java.rmi.RemoteException;
  import javax.ejb.CreateException;
  import javax.ejb.EJBHome;

  //定义主接口,必须继承EJBHome
  public interface HelloHome extends EJBHome {
   //定义EJB创建方法
   Hello create() throws CreateException, RemoteException;
  }

  2.编写远程接口程序
  在文本编辑器中编辑Hello.java文件,并保存在C:workhello目录下。Hello.java文件的代码为:

  //本接口需要引入的类或接口
  import javax.ejb.EJBObject;
  import java.rmi.RemoteException;

  //定义远程接口,必须继承EJBObject
  public interface Hello extends EJBObject {
   //定义业务逻辑方法
   public String sayHello()
   throws RemoteException;
  }

  3.编写Bean类实现程序
  在文件编辑器中编辑HelloBean.java文件,并保存在C:workhello目录下。HellloBean.java文件的代码为:

  //本类需要引入的类或接口
  import javax.ejb.CreateException;
  import javax.ejb.SessionBean;
  import javax.ejb.SessionContext;

  //实现业务逻辑,必须实现SessionBean接口
  public class HelloBean implements SessionBean {
   //这是个会话EJB,声明会话上下文
   private SessionContext ctx;
   //声明字符串
   private String words;
   //接口SessionBean中定义的方法,必须实现
   public void setSessionContext(SessionContext ctx) {
    this.ctx = ctx;
   }
   //接口SessionBean中定义的方法,必须实现
   public void ejbActivate() {
   }
   //接口SessionBean中定义的方法,必须实现
   public void ejbPassivate() {
   }
   //接口SessionBean中定义的方法,必须实现
   public void ejbRemove() {
   }
   //和主接口定义对应的方法,必须实现
   public void ejbCreate() throws CreateException {
    words = "Hello World";
   }
   //供客户端调用的业务逻辑方法,这里只简单的打印字符串,并把字符串返回到客户端
   public String sayHello()
   {
    System.out.println("I am in an EJB of Server ."+words);
    return words;
   }
  }




2.2.2 EJB代码编译

  首先打开命令窗口,进入C:workhello目录,运行环境变量脚本程序:
   c:workhello>c:worksetEnv
  建立build目录:
   c:workhello>md build
  执行编译命令:
   c:workhello>java -d build Hello.java HelloHome.java HelloBean.java
  其中:-d build 表示编译生成的class文件放在build目录中。

2.2.3 EJB部署文件编写

  部署文件是EJB的重要组成部分。简单地说,部署文件就是EJB的说明文件,这个文件由服务器容器使用,服务器根据部署文件的说明来管理EJB。
  EJB部署文件是标准的XML文件,必须遵守XML的语法规则。此外,还要遵守相关的DTD规则。
  部署文件到少有两个文件ejb-jar.xml和weblogic-ejb-jar.xml。前者为EJB自身的一些特征,如名称、组成等:后者是和EJB部署相关的描述。
  编写部署文件:
  (1)在文件编辑器中编辑ejb-jar.xml文件,并保存在C:workhello目录下。ejb-jar.xml文件的内容为:


<?xml version="1.0"?>

<!DOCTYPE ejb-jar PUBLIC -//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd>
<!--EJB说明文件-->
<ejb-jar>
<small-icon>images/green-cube.gif</small-icon>
<enterprise-beans>
<!--定义会话EJB-->
<session>
<small-icon>images/orange-cube.gif</small-icon>
<!--定义会话EJB名-->
<ejb-name>MyFirstEJB</ejb-name>
<!--定义会话EJB主接口名-->
<home>HelloHome</home>
<!--定义会话EJB远程接口名-->
<remote>Hello</remote>
<!--定义会话EJB实现类名-->
<ejb-class>HelloBean</ejb-class>
<!--定义会话EJB类型-->
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<!--定义会话EJB装配描述-->
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>MyFirstEJB</ejb-name>
<method-intf>Remote</method-intf>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>

  (2)在文件编辑器中编辑weblogic-ejb-jar.xml文件,并保存在C:workhello目录下。weblogic-ejb-jar.xml文件的内容为:


<?xml version="1.0"?>

<!DOCTYPE weblogic-ejb-jar PUBLIC -//BEA Systems, Inc.//DTD WebLogic 5.1.0 EJB//EN http://www.bea.com/servers/wls510/dtd/weblogic-ejb-jar.dtd>
<!--EJB部署说明文件-->
<weblogic-ejb-jar>
<weblogic-enterprise-bean>
<!--EJB名-->
<ejb-name>MyFirstEJB</ejb-name>
<!--定义EJB最大缓冲池-->
<caching-descriptor>
<max-beans-in-free-pool>100</max-beans-in-free-pool>
</caching-descriptor>
<!--定义EJB jndi名称-->
<jndi-name>HelloHome</jndi-name>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>

2.2.4 打包

  把上面开发的所有文件打成jar文件包。这些文件包括一三个类文件:Hello.class、HelloHome.class、HelloBean.class和部署文件:ejb-jar.xml,weblogic-ejb-jar.xml。打包时,文件放置的位置是严格要求的。具体为:*.class文件放在当前目录(即C:workhellouild目录下),部署文件必须入在下一级目录Meta-inf中(即C:workhellouildMeta-inf目录下)。如果EJB包含图像文件,则图像文件必须在build目录的下一级目录images中(即C:workhellouildimages目录下)。
  具体操作步骤为:
  (1)在build目录中创建Meta-inf目录,当前路径为C:workhello,执行:
   c:workhello>md buildMeta-inf
  (2)把部署文件拷贝到helloMeta-inf目录下:
   c:workhello>copy *.xml buildMeta-inf
  (3)执行:
   c:workhello>md buildimages
   c:workhello>copy *.gif buildimages
  当然,本例中没有使用图像文件,所以可以免去此步骤。
  (4)用jar命令在build目录下打包。当前路径是c:workhello,运行:
   c:workhello>cd build
   c:workhelloulid>jar cv0f std_myfirstejb_hello.jar META-INF *.class images
   c:workhellouild>cd..
  其中:jar是Jdk中的打包命令:cv0f是命令参数;std_myfirstejb_hello.jar是生成的文件名,由用户指定。
  命令执行完后,在目录build中应该生成文件std_myfirstejb_hello.jar。
  至此,打包完成。

2.2.5 编译生成窗口代码

  Weblogic Server提供了编译生成容器代码的工具,它是一个java程序weblogic.ejbc。在命令行窗口中执行:
  c:workhello>java weblogic.ejbc -compiler javac buildstd_myfirstejb_hello.jar buildmyfirstejb_hello.jar
  可以看出ejbc把std_myfirstejb_hello.jar文件编译成myfirstejb_hello.jar,它包括了Weblogic Server平台可以识别的ejb容器代码。
  如果运行成功,则在build目录下产生myfirstejb_hello.jar文件。

2.3 命令脚本文件

  上面在EJB的开发过程中使用命令行的方式,我们可以把有所有这些命令行集中起来做成一个命令脚本文件build.cmd,使用它可以一次性执行这些命令,而不必一个命令一个命令的执行。该文件存放在C:workhello目录下,其内容为:

md build
javac -d build Hello.java HelloHome.java HelloBean.java
md buildMeta-inf
copy *.xml buildMeta-inf
md buildimages
copy *.gif buildimages
cd build
jar cv0f std_myfirstejb_hello.jar META-INF *.class images
cd ..
java weblogic.ejbc -compiler javac buildstd_myfirstejb_hello.jar buildmyfirstejb_hello.jar

  这样,在程序代码编辑好的情况下,只运行这个命令脚本程序,就可以完成EJB开发。




2.4 EJB部署

  EJB的部署有很多种方法,最简单的一种就是把C:workhellouild目录下的myfirstejb_hello.jar文件拷贝到服务器的applications目录下,即C:eawlserver6.0configmydomainapplications目录下。如果服务器已经启动,则在拷贝的时候不需要重新启动服务器。服务器会自动检测到新拷贝的EJB。

2.5 EJB运行测试

  编写一个简单的客户端程序HelloClient来测试已部署的ejb。

2.5.1 客户端测试程序代码编写

  在文本编辑器中编辑HelloClient.java文件,并保存在C:workhello目录下,其代码如下:

//本类需要引入的类或接口
import java.rmi.RemoteException;
import java.util.Properties;
import javax.ejb.CreateException;
import javax.ejb.RemoveException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

/**
* 这是EJB的客户端测试程序
*/

public class HelloClient {

private static final String JNDI_NAME = "HelloHome";

private String url;
private HelloHome home;

public HelloClient(String url)
throws NamingException
{

this.url = url;

home = lookupHome();
}

void test()
throws RemoteException,CreateException
{
Hello hello = (Hello) PortableRemoteObject.narrow(home.create(), Hello.class);
System.out.println("I am in client. "+hello.sayHello());
}


/**
* 运行这个实例:
* java HelloClient t3://localhost:7001
*/
public static void main(String[] args) throws Exception {

System.out.println(" 客户端程序测试开始... ");

String url = "t3://localhost:7001";

// 解析命令行
if (args.length != 1) {
System.out.println("用法: java HelloClient t3://hostname:port");
return;
} else {
url = args[0];
}
HelloClient client = null;
try {
client = new HelloClient(url);
} catch (NamingException ne) {
System.exit(1);
}
try {
client.test();
} catch (Exception e) {
System.exit(1);
}
System.out.println(" 客户端程序测试结束... ");
}


/**
* 查找 EJB 的主接口
*/
private HelloHome lookupHome()
throws NamingException
{
Context ctx = getInitialContext();
Object home = ctx.lookup(JNDI_NAME);
return (HelloHome) PortableRemoteObject.narrow(home, HelloHome.class);
}

/**
* 使用属性对象获取上下文
*/
private Context getInitialContext() throws NamingException {
Properties h = new Properties();
h.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
h.put(Context.PROVIDER_URL, url);
return new InitialContext(h);
}
}

2.5.2 客户端测试程序代码编译

  请执行以下操作:
  (1)在hello目录下创建client子上当放置客户端测试程序,创建client目录,拷贝文件。执行:
   c:workhello>md client
   c:workhello>copy HelloClient.java client
  注意:因为HelloClient类需引入Hello和HelloHome接口,因此要从build目录下拷贝Hello.class和HelloHome.class文件到client目录。

   c:workhello>copy buildHello.class client
   c:workhello>copy buildHelloHome.class client
  (2)进入client目录
   c:workhello>cd client
  (3)编译:
   c:workhelloclient>java HelloClient.java
  至此客户端测试程序代码编译完毕。
  也可以把这些命令做成一个命令脚本文件build_client.cmd,保存在C:workhello目录,其代码如下:

md client
copy HelloClient.java client
copy buildHello.class client
copy buildHelloHome.class client
cd client
javac HelloClient.java

2.5.3 运行测试

  运行测试程序,执行如下操作:
  (1)启动Weblogic Server 6.0的缺省服务器,Weblogic Server的启动是个简单的过程,可以通过开始菜单和直接运行启动命令脚本两种方式,详细情况请参见第1章。
  (2)运行测试程序。在命窗口中进入C:workhelloclient目录,执行:
   c:workhelloclient>java HelloClient t3://127.0.0.1:7001
  (3)观察运行结果:应该如下:
  客户端程序测试开始...
  I am in client. Hello World
  客户端程序测试结束...
而在Weblogic Server的命令行窗口中打印如下信息:
  I am in an EJB of Server .Hello World
并且每运行一次,这行信息就打印一次。

2.6 常见故障及解决方法

  (1)在命令行窗口中运行javac命令出现:
  "java"不是内部或外部命令,也不是可运行的程序或批处理文件。
  原因:javac.exe命令文件所有的路径没有包含在环境变量Path中。
  (2)执行javac -d build Hello.java HelloHome.java HelloBean.java 命令时出现编译错误,其中有一条错误是:
  cannot resolve symbol
  symbol : class EJBHome
  location : package ejb
  impor javax.ebj.EJBHome;
  原因:javac.exe命令文件甩在的路径没有被包含在环境变量Path中。
  解决方法:运行环境变量脚本命令setEnv.cmd。
  (3)运行客户端测试程序时,即运行:
  java HelloClient t3://127.0.0.1:7001时,出现:
   Exception in thread "main" java.lang.NoClassFoundError: HelloClient
  可能的原因是没有把“.”设置到环境变量classpath中。
  (4)执行java weblogic.ejbc... 命令时,抛出org.xml.sax.SAXParseException异常。
  原因:xml文件有语法错误
  解决办法:进行.xml文件有效性检查。
  (5)执行之后仅显示一行文字程序就结束。
  原因:可能没有部署或者没有正确部署EJB。
  解决办法:仔细查看本书3.4节的内容。

2.7 本章小结

  本章首先讨论如何进行一些准备工作,然后详细介绍了一个简单的EJB的开发过程,包括编写代码、编译、打包、部署和测试运行。通过本章的学习,以期对J2EE的开发有一个感性的认识。
  接下来的第3章到第7章将全面深入的讨论EJB应用及其开发的有关问题。

原文转自:http://www.ltesting.net