Enterprise JavaBeans Distilled(1)
写作动因:
鉴于Enterprise JavaBeans(简称,EJB)技术本身的魅力,EJB开发者,企业商务J2EE应用系统,现有中文资料的缺乏,个人的兴趣等等构成了本人写作本文的源泉。本人水平有限,不对的地方,望来函、来信批评指正!谢谢!
另一方面,EJB技术现在成了很多产品的卖点,所以对于开发者来说,掌握这种技能变得很重要。EJB技术诞生的时间不长,在国内应用也刚刚起步,国内也有不少这方面的资料、书籍,但都有这样几个毛病。第一,内容没有深度,比如用什么工具开发一个EJB实例,一步一步教会读者具体应用,这种内容对于初学者而言有一定帮助。第二,EJB技术是很好的,为什么好呢?我们都会去用它,我想很多人都忽视了技术本身的内部机理。第三,每个技术领域都有自己的核心内容,这些资料都没有教会读者如何面对新技术快熟的切入到核心层的方法,如果以后出现了Java 3呢?等等这些问题,是我们值得考虑的。在国外,EJB技术用的很多,通过
其实,EJB技术尽管复杂、难学,但还是有很好的办法来学的,就像UML一样,抓住根本、先不管细节部分,这也是本文的题目用意所在!
带上这些问题,开始我们的EJB技术之旅。希望大家旅途愉快。
EJB技术是Sun公司发明的,从发明至今已经发布了3个版本的EJB规范,1.0,1.1,2.0。EJB 2.1版已经发布了被提义的最终草案(
EJB技术将TP monitors和distributed-component services中的优点吸收过来,同时把它们的缺点抛弃掉。TP monitors是一种运行用过程语言,比如COBOL、PL/1,编写的应用程序可靠、功能强大的平台,该平台管理应用环境,比如事务性、安全性、资源管理、负载均衡、容错等方面。所以这种平台优势给mission-critical企业级应用程序提供了很好的基础架构。同时,TP monitors采用业界先进的3层体系结构,即由表示层、商业逻辑层和后端资源组成。distributed-component services提供了更为先进的3层体系结构,即把商业对象、组件放置在中间层,其他的进程可以通过其提供的romote proxies来访问本身(熟悉CORBA、Java RMI、DCOM的朋友,都知道这一点)。
分布式组件和负荷在传统的TP monitors的基于过程的应用程序相比,其优点在于,它提供了更好的重用性和灵活性,因为它们可以将不同种类的商业对象集成起来,但这样的组件很难编写,同时缺少TP monitors所提供的健壮的基础框架。如果能够将两者的优势结合起来,便构成EJB出现的缘由。EJB服务器给distributed components提供了类似TP monitors的环境。EJB服务器中,类似TP monitors环境的给出减少了开发的复杂度、distributed components的给出使得开发者的开发效率大大提高。
EJB客户通过JNDI、Java RMI-IIOP来访问。这种客户可能是Java应用程序、JSP(Servlets)、其他的EJB或者用其他语言写的应用。
Sun公司给EJB Architecture下的定义:
The Enterprise JavaBeans architecture is a component architecture for the development and deployment of componentbased distributed business applications. Applications written using the Enterprise JavaBeans architecture are scalable, transactional, and multi-user secure. These applications may be written once, and then deployed on any server platform that supports the Enterprise JavaBeans specification.
这样一种定义反映出,EJB适合mission-critical企业级应用。
文章组织结构:
该系列文章主要以EJB 2.0规范涉及到的技术为主。开发工具建议采用JBuilder 7、服务器自己随意。本人采用WebLogic 7.0。关于两者的集成,建议大家最好看看Borland提供的集成白皮书,链接地址本人前面的文章中给出过。
每一次文章都会给出EJB中一个关键技术的分析,或者是设计实例。
-------------------------------------------------------------
要求:
本文假设读者对EJB技术有一定熟悉,对SQL有一定了解就可以了。由于EJB涉及到的技术很多,尽管每次只讲述一种技术,但各种技术是相关的,所以希望读者谅解,因为这样不是很好组织。
数据库: SQL Server 2000
操作系统: Windows 2000
开发工具; JBuilder 7
EJB服务器: WebLogic 7.0
机器IP地址,10.11.12.58
实例综述:通过无状态Session Beans得到容器管理的Entity Beans中的数据,然后把无状态Session Beans得到的数据给JSP页面,从而客户可以看到所要的结果。通过这样一种过程使得您知道编写EJB组件是多么简单的事情。
配置好SQL Server 2000的JDBC驱动(微软网站有下载,或者用BEA提供的也可以!该例子中用的是微软的JDBC)、JBuilder 7 + WebLogic 7集成环境,其他的也可以。
1. 配置JDBC数据源:这个过程包括两个步骤,首先配置连接池(Connection Pools)。(为什么采用连接池:开发人员不想编写Database方面的代码、更换数据库系统变得简单、限制数据库的连接数量、不需要为每个客户建立新连接。这种池的概念在J2EE中有很多地方出现了,比如EJB本身)配置的参数如下:
Name: cacd
URL: jdbc:microsoft:sqlserver://10.11.12.58:1433;user=sa;password=cacd;
Driver ClassName: com.microsoft.jdbc.sqlserver.SQLServerDriver
Initial Capacity: 3
Maximum Capacity: 10
其次,配置JDBC数据源,在Tx Data Sources中配置的参数如下:
Name: cacd
JNDI Name: cacd
Pool Name: cacd(要与前面的相匹配!)
(Tx Data Sources与一般的Data Sources 区别何在?读给读者思考、讨论。)
其中,在URL中,你需要为SQL Server 2000配置一个用户名sa,密码为cacd,因为这里用的是Type 4的JDBC,所以需要将SQL Server 2000的用户认证修改为:NT+SQL Server 2000混合认证。
2. 数据库的建立:Entity Beans代表了Database中的数据,所以需要数据库支持,但一般情况下,我们知道,可以根据容器管理的Entity Beans导出SQL DDL。另一方面,可以根据SQL DDL生成容器管理的Entity Beans。两种方法都可以。比如JBuilder 7两种方法都提供了。但我想,信息模型(数据库)的建立在编码之前就应该存在,所以建议采用第二种办法。当然有些时候第一种会较为合理些,因为并不是表中所有的字段都会映射到Entity Beans中。该例子中建立了这样这样一个Table:
/*===================================================*/
/* Table : techniquespec */
/*===================================================*/
create table techniquespec (
techniqueitem char(100) not null,
units char(10) null,
minvalue decimal(16,6) null,
maxvalue decimal(16,6) null,
types char(1) null,
signon char(1) null,
constraint PK_TECHNIQUESPEC primary key (techniqueitem)
)
其中,开发人员在建表的过程中,不需要手工去写SQL DDL语句,一般都可以借助于工具进行,比如PowerDesigner、ERWin等工具。用用就会了,不要对工具产生不好的情绪,但前提是你熟悉数据库理论。
用户建好Table后,可以填入数据,中文的也可以。
3. 容器管理的Entity Beans的开发:JBuilder对EJB开发支持的比较好,提供了图形化的方式。由于我们已经建立好了Database,前面的techniquespec表,我们可以借助于Import Schema From Database,将SQL DLL引入进来。(由于这里不能贴出操作图片,所以只能用文字说明梗概,大家在设计过程中有什么问题,可以发邮件给我,我尽力而为。)在这个过程中,一定要注意JNDI的名字和数据源中的JNDI要一致。得到SQL DLL后,我们可以根据techniquespec表生成CMP 2.0 Entity Beans,在这里我们采用LocalHome访问Entity Beans,为什么采用?后续文章中都会详细阐述。现在想返回表techniquespec中列techniqueitem的所有内容。首先,真假一个findByTypes Finder方法,EJB QL语句为: SELECT OBJECT(p) from Techniquespec AS p,其中返回值为Collection。下面给出代码。
LocalHome接口:
Local接口:
bean类:
4. 无状态Session Beans的开发: 通过EJB 图形设计器,生成一个Session Bean,代码如下。
Home接口:
Remote接口:
bean类:
说明:(1)我们在Session Bean中添加了一个商务方法,getVocTechnique(),以获得techniqueitem中的全部内容。(2)setSessionContext中,我们完成了EJB的一些初始化工作。(3) charASC.chinTOISO是用于中文转换的静态方法,代码如下:
5. JSP页面的开发:针对Session Bean,我编写了一个JSP页面。
<%@page contentType="text/html;charset=gb2312"%>
<%@page import="java.text.*" %>
<%@page import="java.util.*"%>
<%@page import="java.sql.*" %>
<%@page import="javax.naming.*" %>
<%@page import="java.lang.*" %>
<%@page import="javax.rmi.PortableRemoteObject" %>
<%@page import="javax.ejb.* "%>
<%@page import="cacdsystem.*"%>
<html>
<head>
<title>产品技术需求提取</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body>
<form id=form name=form1 method=post>
<input type=hidden id=pageFlag name=pageFlag value=input>
<table cellSpacing=0 cellPadding=0 width="98%" border=0 align=center >
<tr height=30 class=titleFont>
<td><font color=#0058a5> 您所在位置:产品技术需求提取</font></td>
</tr>
<tr height=1 class=titleFont>
<td></td>
</tr>
</table>
<table width="98%" border="0" bgcolor=#999999 align=center>
<tr>
<td><b> <font color="#ffffff">产品技术需求提取</font></b></td>
</tr>
</table>
<table width="98%" border="1" align=center bgcolor="#f0f0f0" bordercolor=#ffffff cellspacing=0 cellpadding=0 class=titleFont>
<tr bgcolor=#e0e8f8>
<td> </td>
</tr>
<%
InitialContext ctx = new InitialContext();
VocHome vocHome =
(VocHome)PortableRemoteObject.narrow(ctx.lookup("Voc"),VocHome.class);
Voc voc = vocHome.create();
Collection collection = voc.getVocTechnique();
if(collection.size() > 0)
{
Iterator iters = collection.iterator();
int i = 0;
while(iters.hasNext())
{
++i;
%>
<tr>
<td><input type=checkbox name=<%= "select"+i %>
value=<%= i %>><%= (String)iters.next() %><br></td>
</tr>
<%
}
}
%>
<%
voc.remove();
%>
<tr bgcolor=#e0e8f8 align=middle>
<td>
<p align=left></p>
</td>
</tr>
<tr align=middle>
<td>
<input type=submit id=submit1 name=submit1 value="提 交">
<input type=reset id=submit1 name=submit value="重 置">
</td>
</tr>
</table>
</form>
</body>
</html>
6. 系统Deploy: 到现在为止,我们实现了Entity Bean、Session Bean、JSP,从而实现了该实例所需要的代码。为使我们测试代码的正确性,我们来Deploy到服务器上。首先,由于在Session Bean中引用了Entity Bean,所以需要申明。
<session>
<display-name>Voc</display-name>
<ejb-name>Voc</ejb-name>
<home>cacdsystem.VocHome</home>
<remote>cacdsystem.Voc</remote>
<ejb-class>cacdsystem.VocBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-local-ref> //手工添加的配置描述符代码!
<description />
<ejb-ref-name>Techniquespec</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<local-home>cacdsystem.TechniquespecHome</local-home>
<local>cacdsystem.Techniquespec</local>
<ejb-link>Techniquespec</ejb-link>
</ejb-local-ref>
</session>
其次,需要将EJB的接口文件拷贝到web-inf\classes目录下。在这里由于是存在package cacdsystem中,需要把4个接口文件拷贝到web-inf\classes\cacdsystem中。第三,将EJB打包成.jar文件,JBuilder 7可以自动完成,记得要包括charASC.class文件。生成.jar后发布到服务器上可以通过JBuilder 7发布,也可以通过WebLogic提供的Builder工具,或者通过Console发布,或者通过将.jar拷贝到applications目录即达到发布的目的。
最后,我们也可以通过把整个EJB、JSP打包成.ear文件,JBuilder工具提供了Wizard。
整个过程实现了EJB组件开发,从而对EJB有了一定的认识。接下来的文章中,我会继续深入讲述EJB技术涉及到的技术。谢谢大家看完我的写文章,也希望大家写信和我交流
-------------------------------------------------------------
通过前两次,大家对EJB有了大概的了解,当然细节部分您可以参考我给出的参考资料。这次的主要任务是分析Enterprise JavaBeans 2.0 Specification。规范的PDF下载版本地址在http://java.sun.com/products/ejb/docs.html,这个地方。为什么将规范作为一次内容来讲呢?
本人认为。第一,如果您没有看过EJB规范,是否就一定了解EJB的真正意义?因为我们知道Java相关的东西,都是通过JCP组织(http://www.jcp.org )发布相关规范来给出各个技术所包含的内容,所以通过分析规范我们可以对EJB有更好的认识。第二,不要把会开发EJB组件作为自己的终极目标。我们知道,软件工程的使用使得软件开发将会越来越简单,比如举一个简单的例子,Together,不知道大家用过没有?Java语言本身推荐有编码要求,如果开发人员需要自己维护代码的风格很头疼,Together给你做好了,简单的快捷方式使得你减少工作量。所以你需要研究EJB规范,注重EJB技术的底层内容。第三,如果您研究过EJB规范,是否觉得将近600页的内容使得您很费力去分析、研究。所以在这里给出一些建设性的意见辅助您学习。
进入正题。。。
首先让我们看看EJB 2.0中主要增加了什么内容。这些内容自然是我们要研究的重点。
(1) 通过集成EJB和JMS,引入一种新的EJB,消息驱动Bean(Message-Drivern Beans)。消息驱动Bean是一种无状态、异步处理消息、非分布式组件(实现过程中不需要实现EJBHome、EJBOject接口),其开发过程很简单。建议学习方式:需要JMS基础,和一定的EJB基础,然后结合一些应用实例可以开始学习,推荐J2EE Tutorial,JBuilder 7帮助中提供的例子也不错,或者Enterprise JavaBeans,3rd这本书中的例子。
(2) EJB 2.0中,用于CMP的Entity Beans作了很大的修改,并且引入了CMR,容器管理关系。其中,用于管理Entity Beans间关系的CMR的引入给我们带来很大的便利。EJB QL也是不错的新东西。还有一些提高性能方面的改进。建议看看J2EE Tutorial中的例子,仔细分析分析,http://www.theserverside.com 上有不少这方面较为深入的分析。
(3) Local接口的引入。在EJB组件的开发上,开发人员的开发方式没有多大改变,但这种改变带来了其他很重要的东西。比如,性能上的提高,因为EJB客户不需要采用分布式协议访问该EJB组件。还有,Local接口使得CMR成为可能,如果你开发过EJB 1.1组件,就需要自己去管理Beans之间的关系。建议,同上。
(4) EJB QL的引入。类似SQL 的东西,但操作对象不一样,可以说EJB QL实现了SQL的子集。建议:同上,同时我会专门有一次专题讲述EJB QL。
(5) EJB安全方面的加强:通过角色宣称(role declarative)实现。建议参考Enterprise JavaBeans,3rd.
(6) 允许EJB客户可以是不同产品上的J2EE组件。
这些内容是EJB 2.0中介绍的,所以我们要重点注意这些技术。
其次,600页的规范,我们不可能在很短的实践中全部都掌握了。可以结合自己项目中用到的具体开发内容,有选择的学习,但首先一定要知道EJB 2.0规范中的具体内容。
有的放矢
循序渐进,有了这种过程,你每次看EJB 2.0规范过程中会有新的领悟。孔子总结出来的道理。比如,我刚王成一个项目,其中的消息驱动Beans用得比较多,所以结合这些内容把EJB 2.0规范中相应的内容多多研究。
再者,需要您去多看看Enterprise JavaBeans API Reference。这些文档可以去Java网站下载。在Mastering EJB中有详细介绍。
-------------------------------------------------------------
本文的应用服务器以WebLogic为例,其他的服务器过程差不多。
在基于J2EE平台中,EJB的开发属于重中之重。本文试着从几方面,讲述了常用的开发模式和方法。无论是给初学者,还是有经验的朋友都有一定的参考价值。
大家知道,EJB对于初学者来说是一个很头疼的问题,无论是开发还是发布、测试,尤其是Entity Beans更为头疼,所以本文介绍几种用于设计、开发、测试的方法,以供参考。
WebLogic平台,作为业界优秀的产品,其本身提供了很多优秀的工具来开发、发布J2EE应用程序。除此之外,和其他集成开发环境,比如JBuilder、VisualCafe以及支持软件开发整个过程的Together ControlCenter。有了业界这样一种方式的支持,使得WebLogic平台的应用更为广泛。
第一种方式:
用一般的软件开发EJB,比如JCreator、EditPlus都可以。对于初学者,用这种方式比较好,能够对EJB的机制有较为深入的了解。编写完后,把所有的EJB源文件放置在一个src的目录下,并在当前目录(和src目录平行)下建立一个目录deployment,并将写好的配置描述文件ejb-jar.xml和weblogic-ejb-jar.xml拷贝目录deployment下。然后你可以将下面的批处理文件拷贝到目录src的父目录中,然后运行批处理文件。(当然,你需要在这之前设置classpath和相关变量,自己推敲以下就知道了)
//用于编译打包EJB的批处理文件compilejar.bat:
mkdir classes
mkdir lib
mkdir classes\META-INF
copy deployment\*.xml classes\META-INF
javac -d classes src\*.java
cd classes
jar cf ..\lib\temp.jar *
cd ..
cd lib
java weblogic.ejbc -keepgenerated temp.jar xxxEJB.jar
del temp.jar
cd ..
//最终,我们得到了XXXEJB.jar,也就是可以用来直接在WebLogic中发布的jar文件
其中编译EJB我们用到weblogic.ejbc,老版本的WebLogic用的是weblogic.ejbc20。(注: WebLogic中EJB的编译是预编译,也就是说会生成EJB所需的所有的目标文件,但有些应用服务器不是这样的,比如JBoss借助于反射机制在运行期动态生成!)
我们从而得到了xxxEJB.jar,发布到WebLogic上。如果不借助于其他工具,只用WebLogic自己的辅助工具的话,有两种方式可以选择。其一,通过Console台,这种方式最简单了,您应该大体上知道如何弄了。其二,通过WebLogic提供的startWLBuilder.cmd工具。启动后首先要连接到WebLogic中,如图1(图略)所示。步骤是主菜单-〉Tools-〉Connect to Server。
然后连接上服务器后,打开要deploy的EJB,或者Web Application。然后就可以发布了。这两种办法都可以。当然,个人喜欢第二中,因为它可以检查你的EJB打包是否符合要求,同时你需要修改EJB中的配置描述符都很简单,这种图形化的界面操作很方便,从而大大提高deploy的成功率。
第二种方式:
通过第一种方式,我想您也体会到不少东西。当然,大家会想,这样的一种方式还是比较麻烦,至少需要更换两种工具,不舒服。那好,接下来我们介绍第二种方式。与IDE的集成。通过JBuilder Enterprise提供的集成我们可以更加智能的完成工作。关于JBuilder与WebLogic的集成过程,Borland网站,http://bdn.borland.com/,上有两篇分别介绍JBuilder 6 + WebLogic 6.1和JBuilder 7 + WebLogic 7.0的白皮书。
这种方式的引入,使得J2EE应用程序的开发、发布和测试都是在一个统一的环境下进行的,可以大大提高生产效率,使得开发人员可以更加专注于软件本身。
第三种方式:
现在的开发工具、集成开发环境慢慢的很难和软件前期的需求分析、系统建模联系起来,这也是IDE所面临的困境。比如,JBuilder提供了数量有限的UML图以支持软件产品开发。而作为Together ControlCenter,由于其对软件工程的整个过程支持力度很高,所以慢慢流行起来。
Together ControlCenter中内置的BEA WebLogic Application Server PlugIn使得该支持建模、开发、部署J2EE应用程序的工具获得在WebLogic平台下开发软件的开发人员的青睐。如图2(图略)所示。
该平台支持开发人员在开发阶段更换应用服务器,无论是同一服务器的不同版本,还是不同服务器。
综上所述,本文介绍了3种开发EJB的方式,在实际应用中也是使用的模式,开发者可以根据自己的喜好来选择不同的模式。
1. Enterprise JavaBeans, 3rd Edition by Richard Monson-Haefel 个人认为最好的EJB书!
2. Effective Java Programming Language Guide by Joshun Bloch(中文版翻译的不太好,个人观点)
3. Thinking in Java ,2nd Edition by Bruce Eckel(侯捷翻译的中文版也不错)
4. http://www.theserverside.com
5. http://java.sun.com/j2ee/tutorial/1_3-fcs/ Enterprise JavaBeans Technology部分
6. http://www.ejbnow.com/ 很有价值的网站!
7. http://java.sun.com/products/ejb/
写作动因:
鉴于Enterprise JavaBeans(简称,EJB)技术本身的魅力,EJB开发者,企业商务J2EE应用系统,现有中文资料的缺乏,个人的兴趣等等构成了本人写作本文的源泉。本人水平有限,不对的地方,望来函、来信批评指正!谢谢!
另一方面,EJB技术现在成了很多产品的卖点,所以对于开发者来说,掌握这种技能变得很重要。EJB技术诞生的时间不长,在国内应用也刚刚起步,国内也有不少这方面的资料、书籍,但都有这样几个毛病。第一,内容没有深度,比如用什么工具开发一个EJB实例,一步一步教会读者具体应用,这种内容对于初学者而言有一定帮助。第二,EJB技术是很好的,为什么好呢?我们都会去用它,我想很多人都忽视了技术本身的内部机理。第三,每个技术领域都有自己的核心内容,这些资料都没有教会读者如何面对新技术快熟的切入到核心层的方法,如果以后出现了Java 3呢?等等这些问题,是我们值得考虑的。在国外,EJB技术用的很多,通过
其实,EJB技术尽管复杂、难学,但还是有很好的办法来学的,就像UML一样,抓住根本、先不管细节部分,这也是本文的题目用意所在!
带上这些问题,开始我们的EJB技术之旅。希望大家旅途愉快。
开题
EJB技术是Sun公司发明的,从发明至今已经发布了3个版本的EJB规范,1.0,1.1,2.0。EJB 2.1版已经发布了被提义的最终草案(
EJB技术将TP monitors和distributed-component services中的优点吸收过来,同时把它们的缺点抛弃掉。TP monitors是一种运行用过程语言,比如COBOL、PL/1,编写的应用程序可靠、功能强大的平台,该平台管理应用环境,比如事务性、安全性、资源管理、负载均衡、容错等方面。所以这种平台优势给mission-critical企业级应用程序提供了很好的基础架构。同时,TP monitors采用业界先进的3层体系结构,即由表示层、商业逻辑层和后端资源组成。distributed-component services提供了更为先进的3层体系结构,即把商业对象、组件放置在中间层,其他的进程可以通过其提供的romote proxies来访问本身(熟悉CORBA、Java RMI、DCOM的朋友,都知道这一点)。
分布式组件和负荷在传统的TP monitors的基于过程的应用程序相比,其优点在于,它提供了更好的重用性和灵活性,因为它们可以将不同种类的商业对象集成起来,但这样的组件很难编写,同时缺少TP monitors所提供的健壮的基础框架。如果能够将两者的优势结合起来,便构成EJB出现的缘由。EJB服务器给distributed components提供了类似TP monitors的环境。EJB服务器中,类似TP monitors环境的给出减少了开发的复杂度、distributed components的给出使得开发者的开发效率大大提高。
EJB客户通过JNDI、Java RMI-IIOP来访问。这种客户可能是Java应用程序、JSP(Servlets)、其他的EJB或者用其他语言写的应用。
Sun公司给EJB Architecture下的定义:
The Enterprise JavaBeans architecture is a component architecture for the development and deployment of componentbased distributed business applications. Applications written using the Enterprise JavaBeans architecture are scalable, transactional, and multi-user secure. These applications may be written once, and then deployed on any server platform that supports the Enterprise JavaBeans specification.
这样一种定义反映出,EJB适合mission-critical企业级应用。
文章组织结构:
该系列文章主要以EJB 2.0规范涉及到的技术为主。开发工具建议采用JBuilder 7、服务器自己随意。本人采用WebLogic 7.0。关于两者的集成,建议大家最好看看Borland提供的集成白皮书,链接地址本人前面的文章中给出过。
每一次文章都会给出EJB中一个关键技术的分析,或者是设计实例。
-------------------------------------------------------------
设计实例的深入分析
-------------------------------------------------------------要求:
本文假设读者对EJB技术有一定熟悉,对SQL有一定了解就可以了。由于EJB涉及到的技术很多,尽管每次只讲述一种技术,但各种技术是相关的,所以希望读者谅解,因为这样不是很好组织。
实例背景
数据库: SQL Server 2000
操作系统: Windows 2000
开发工具; JBuilder 7
EJB服务器: WebLogic 7.0
机器IP地址,10.11.12.58
实例综述:通过无状态Session Beans得到容器管理的Entity Beans中的数据,然后把无状态Session Beans得到的数据给JSP页面,从而客户可以看到所要的结果。通过这样一种过程使得您知道编写EJB组件是多么简单的事情。
准备工作
配置好SQL Server 2000的JDBC驱动(微软网站有下载,或者用BEA提供的也可以!该例子中用的是微软的JDBC)、JBuilder 7 + WebLogic 7集成环境,其他的也可以。
开发过程
1. 配置JDBC数据源:这个过程包括两个步骤,首先配置连接池(Connection Pools)。(为什么采用连接池:开发人员不想编写Database方面的代码、更换数据库系统变得简单、限制数据库的连接数量、不需要为每个客户建立新连接。这种池的概念在J2EE中有很多地方出现了,比如EJB本身)配置的参数如下:
Name: cacd
URL: jdbc:microsoft:sqlserver://10.11.12.58:1433;user=sa;password=cacd;
Driver ClassName: com.microsoft.jdbc.sqlserver.SQLServerDriver
Initial Capacity: 3
Maximum Capacity: 10
其次,配置JDBC数据源,在Tx Data Sources中配置的参数如下:
Name: cacd
JNDI Name: cacd
Pool Name: cacd(要与前面的相匹配!)
(Tx Data Sources与一般的Data Sources 区别何在?读给读者思考、讨论。)
其中,在URL中,你需要为SQL Server 2000配置一个用户名sa,密码为cacd,因为这里用的是Type 4的JDBC,所以需要将SQL Server 2000的用户认证修改为:NT+SQL Server 2000混合认证。
2. 数据库的建立:Entity Beans代表了Database中的数据,所以需要数据库支持,但一般情况下,我们知道,可以根据容器管理的Entity Beans导出SQL DDL。另一方面,可以根据SQL DDL生成容器管理的Entity Beans。两种方法都可以。比如JBuilder 7两种方法都提供了。但我想,信息模型(数据库)的建立在编码之前就应该存在,所以建议采用第二种办法。当然有些时候第一种会较为合理些,因为并不是表中所有的字段都会映射到Entity Beans中。该例子中建立了这样这样一个Table:
/*===================================================*/
/* Table : techniquespec */
/*===================================================*/
create table techniquespec (
techniqueitem char(100) not null,
units char(10) null,
minvalue decimal(16,6) null,
maxvalue decimal(16,6) null,
types char(1) null,
signon char(1) null,
constraint PK_TECHNIQUESPEC primary key (techniqueitem)
)
其中,开发人员在建表的过程中,不需要手工去写SQL DDL语句,一般都可以借助于工具进行,比如PowerDesigner、ERWin等工具。用用就会了,不要对工具产生不好的情绪,但前提是你熟悉数据库理论。
用户建好Table后,可以填入数据,中文的也可以。
3. 容器管理的Entity Beans的开发:JBuilder对EJB开发支持的比较好,提供了图形化的方式。由于我们已经建立好了Database,前面的techniquespec表,我们可以借助于Import Schema From Database,将SQL DLL引入进来。(由于这里不能贴出操作图片,所以只能用文字说明梗概,大家在设计过程中有什么问题,可以发邮件给我,我尽力而为。)在这个过程中,一定要注意JNDI的名字和数据源中的JNDI要一致。得到SQL DLL后,我们可以根据techniquespec表生成CMP 2.0 Entity Beans,在这里我们采用LocalHome访问Entity Beans,为什么采用?后续文章中都会详细阐述。现在想返回表techniquespec中列techniqueitem的所有内容。首先,真假一个findByTypes Finder方法,EJB QL语句为: SELECT OBJECT(p) from Techniquespec AS p,其中返回值为Collection。下面给出代码。
LocalHome接口:
- package cacdsystem;
- import javax.ejb.*;
- import java.util.*;
- public interface TechniquespecHome extends javax.ejb.
- {
- public Techniquespec create( techniqueitem) throws ;
- public findByTypes() throws ;//添加的Finder方法
- public Techniquespec findByPrimaryKey( techniqueitem)
- throws ;
- }
Local接口:
- package cacdsystem;
- import javax.ejb.*;
- import java.util.*;
- import java.math.*;
- public interface Techniquespec extends javax.ejb.
- {
- public getTechniqueitem();
- public void setUnits( units);
- public getUnits();
- public void setMinvalue( minvalue);
- public getMinvalue();
- public void setMaxvalue( maxvalue);
- public getMaxvalue();
- public void setTypes( types);
- public getTypes();
- public void setSignon( signon);
- public getSignon();
- }
bean类:
- package cacdsystem;
- import javax.ejb.*;
- abstract public class TechniquespecBean implements
- {
- entityContext;
- public java.lang. ejbCreate(java.lang. techniqueitem)
- throws {
- setTechniqueitem(techniqueitem);
- return null;
- }
- public void ejbPostCreate(java.lang. techniqueitem) throws {
- }
- public void ejbRemove() throws {
- }
- public abstract void setTechniqueitem(java.lang. techniqueitem);
- public abstract void setUnits(java.lang. units);
- public abstract void setMinvalue(java.math. minvalue);
- public abstract void setMaxvalue(java.math. maxvalue);
- public abstract void setTypes(java.lang. types);
- public abstract void setSignon(java.lang. signon);
- public abstract java.lang. getTechniqueitem();
- public abstract java.lang. getUnits();
- public abstract java.math. getMinvalue();
- public abstract java.math. getMaxvalue();
- public abstract java.lang. getTypes();
- public abstract java.lang. getSignon();
- public void ejbLoad()
- {
- }
- public void ejbStore()
- {
- }
- public void ejbActivate()
- {
- }
- public void ejbPassivate()
- {
- }
- public void unsetEntityContext()
- {
- this.entityContext = null;
- }
- public void setEntityContext( entityContext)
- {
- this.entityContext = entityContext;
- }
- }
4. 无状态Session Beans的开发: 通过EJB 图形设计器,生成一个Session Bean,代码如下。
Home接口:
- package cacdsystem;
- import javax.ejb.*;
- import java.util.*;
- import java.rmi.*;
- public interface VocHome extends javax.ejb. {
- public Voc create() throws , ;
- }
Remote接口:
- package cacdsystem;
- import javax.ejb.*;
- import java.util.*;
- import java.rmi.*;
- public interface Voc extends javax.ejb. {
- public getVocTechnique() throws ;
- }
bean类:
- package cacdsystem;
- import javax.ejb.*;
- import java.util.*;
- public class VocBean implements {
- sessionContext;
- TechniquespecHome techniquespecHome;
- public void ejbCreate() throws {
- }
- public void ejbRemove() {
- }
- public void ejbActivate() {
- }
- public void ejbPassivate() {
- }
- public void setSessionContext( sessionContext) {
- this.sessionContext = sessionContext;
- try
- {
- javax.naming. context = new javax.naming.();
- techniquespecHome = (TechniquespecHome)context.lookup("Techniquespec");
- }
- catch ( ex) {
- .out.println("Techniquespecs调用出错!");
- throw new (ex);
- }
- }
- public java.util. getVocTechnique() {
- /**@todo Complete this method*/
- /**
- * 获得全部技术需求项函数!
- */
- .out.println("调用getVocTechnique()!");
- java.util. collection = null;
- java.util. results = new ();
- try
- {
- collection= techniquespecHome.findByTypes();
- if(collection.size() > 0)
- {
- .out.println(collection.size());
- iter = collection.iterator();
- tempStr = null;
- Techniquespec techniqu = null;
- while(iter.hasNext())
- {
- techniqu = (Techniquespec) iter.next();
- tempStr = techniqu.getTechniqueitem();
- tempStr = charASC.chinTOISO(tempStr);
- results.add(tempStr);
- }
- }
- }
- catch ( ex) {
- ex.printStackTrace();
- throw new (ex);
- }
- return results;
- }
- }
说明:(1)我们在Session Bean中添加了一个商务方法,getVocTechnique(),以获得techniqueitem中的全部内容。(2)setSessionContext中,我们完成了EJB的一些初始化工作。(3) charASC.chinTOISO是用于中文转换的静态方法,代码如下:
- package cacdsystem;
- public class charASC
- {
- static private results = null;
- public charASC()
- {
- }
- static public chinTOISO( temp)
- {
- if(temp == null)
- {
- results = "";
- }
- else
- {
- try
- {
- results = new (temp.getBytes("ISO-8859-1"),"gb2312");
- results = results.trim();
- }
- catch( ee)
- {
- .out.println("中文转换失败!");
- }
- }
- return results;
- }
- }
5. JSP页面的开发:针对Session Bean,我编写了一个JSP页面。
<%@page contentType="text/html;charset=gb2312"%>
<%@page import="java.text.*" %>
<%@page import="java.util.*"%>
<%@page import="java.sql.*" %>
<%@page import="javax.naming.*" %>
<%@page import="java.lang.*" %>
<%@page import="javax.rmi.PortableRemoteObject" %>
<%@page import="javax.ejb.* "%>
<%@page import="cacdsystem.*"%>
<html>
<head>
<title>产品技术需求提取</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body>
<form id=form name=form1 method=post>
<input type=hidden id=pageFlag name=pageFlag value=input>
<table cellSpacing=0 cellPadding=0 width="98%" border=0 align=center >
<tr height=30 class=titleFont>
<td><font color=#0058a5> 您所在位置:产品技术需求提取</font></td>
</tr>
<tr height=1 class=titleFont>
<td></td>
</tr>
</table>
<table width="98%" border="0" bgcolor=#999999 align=center>
<tr>
<td><b> <font color="#ffffff">产品技术需求提取</font></b></td>
</tr>
</table>
<table width="98%" border="1" align=center bgcolor="#f0f0f0" bordercolor=#ffffff cellspacing=0 cellpadding=0 class=titleFont>
<tr bgcolor=#e0e8f8>
<td> </td>
</tr>
<%
InitialContext ctx = new InitialContext();
VocHome vocHome =
(VocHome)PortableRemoteObject.narrow(ctx.lookup("Voc"),VocHome.class);
Voc voc = vocHome.create();
Collection collection = voc.getVocTechnique();
if(collection.size() > 0)
{
Iterator iters = collection.iterator();
int i = 0;
while(iters.hasNext())
{
++i;
%>
<tr>
<td><input type=checkbox name=<%= "select"+i %>
value=<%= i %>><%= (String)iters.next() %><br></td>
</tr>
<%
}
}
%>
<%
voc.remove();
%>
<tr bgcolor=#e0e8f8 align=middle>
<td>
<p align=left></p>
</td>
</tr>
<tr align=middle>
<td>
<input type=submit id=submit1 name=submit1 value="提 交">
<input type=reset id=submit1 name=submit value="重 置">
</td>
</tr>
</table>
</form>
</body>
</html>
6. 系统Deploy: 到现在为止,我们实现了Entity Bean、Session Bean、JSP,从而实现了该实例所需要的代码。为使我们测试代码的正确性,我们来Deploy到服务器上。首先,由于在Session Bean中引用了Entity Bean,所以需要申明。
<session>
<display-name>Voc</display-name>
<ejb-name>Voc</ejb-name>
<home>cacdsystem.VocHome</home>
<remote>cacdsystem.Voc</remote>
<ejb-class>cacdsystem.VocBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-local-ref> //手工添加的配置描述符代码!
<description />
<ejb-ref-name>Techniquespec</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<local-home>cacdsystem.TechniquespecHome</local-home>
<local>cacdsystem.Techniquespec</local>
<ejb-link>Techniquespec</ejb-link>
</ejb-local-ref>
</session>
其次,需要将EJB的接口文件拷贝到web-inf\classes目录下。在这里由于是存在package cacdsystem中,需要把4个接口文件拷贝到web-inf\classes\cacdsystem中。第三,将EJB打包成.jar文件,JBuilder 7可以自动完成,记得要包括charASC.class文件。生成.jar后发布到服务器上可以通过JBuilder 7发布,也可以通过WebLogic提供的Builder工具,或者通过Console发布,或者通过将.jar拷贝到applications目录即达到发布的目的。
最后,我们也可以通过把整个EJB、JSP打包成.ear文件,JBuilder工具提供了Wizard。
总结
整个过程实现了EJB组件开发,从而对EJB有了一定的认识。接下来的文章中,我会继续深入讲述EJB技术涉及到的技术。谢谢大家看完我的写文章,也希望大家写信和我交流
-------------------------------------------------------------
EJB 2.0规范研究、学习
-------------------------------------------------------------通过前两次,大家对EJB有了大概的了解,当然细节部分您可以参考我给出的参考资料。这次的主要任务是分析Enterprise JavaBeans 2.0 Specification。规范的PDF下载版本地址在http://java.sun.com/products/ejb/docs.html,这个地方。为什么将规范作为一次内容来讲呢?
本人认为。第一,如果您没有看过EJB规范,是否就一定了解EJB的真正意义?因为我们知道Java相关的东西,都是通过JCP组织(http://www.jcp.org )发布相关规范来给出各个技术所包含的内容,所以通过分析规范我们可以对EJB有更好的认识。第二,不要把会开发EJB组件作为自己的终极目标。我们知道,软件工程的使用使得软件开发将会越来越简单,比如举一个简单的例子,Together,不知道大家用过没有?Java语言本身推荐有编码要求,如果开发人员需要自己维护代码的风格很头疼,Together给你做好了,简单的快捷方式使得你减少工作量。所以你需要研究EJB规范,注重EJB技术的底层内容。第三,如果您研究过EJB规范,是否觉得将近600页的内容使得您很费力去分析、研究。所以在这里给出一些建设性的意见辅助您学习。
进入正题。。。
首先让我们看看EJB 2.0中主要增加了什么内容。这些内容自然是我们要研究的重点。
(1) 通过集成EJB和JMS,引入一种新的EJB,消息驱动Bean(Message-Drivern Beans)。消息驱动Bean是一种无状态、异步处理消息、非分布式组件(实现过程中不需要实现EJBHome、EJBOject接口),其开发过程很简单。建议学习方式:需要JMS基础,和一定的EJB基础,然后结合一些应用实例可以开始学习,推荐J2EE Tutorial,JBuilder 7帮助中提供的例子也不错,或者Enterprise JavaBeans,3rd这本书中的例子。
(2) EJB 2.0中,用于CMP的Entity Beans作了很大的修改,并且引入了CMR,容器管理关系。其中,用于管理Entity Beans间关系的CMR的引入给我们带来很大的便利。EJB QL也是不错的新东西。还有一些提高性能方面的改进。建议看看J2EE Tutorial中的例子,仔细分析分析,http://www.theserverside.com 上有不少这方面较为深入的分析。
(3) Local接口的引入。在EJB组件的开发上,开发人员的开发方式没有多大改变,但这种改变带来了其他很重要的东西。比如,性能上的提高,因为EJB客户不需要采用分布式协议访问该EJB组件。还有,Local接口使得CMR成为可能,如果你开发过EJB 1.1组件,就需要自己去管理Beans之间的关系。建议,同上。
(4) EJB QL的引入。类似SQL 的东西,但操作对象不一样,可以说EJB QL实现了SQL的子集。建议:同上,同时我会专门有一次专题讲述EJB QL。
(5) EJB安全方面的加强:通过角色宣称(role declarative)实现。建议参考Enterprise JavaBeans,3rd.
(6) 允许EJB客户可以是不同产品上的J2EE组件。
这些内容是EJB 2.0中介绍的,所以我们要重点注意这些技术。
其次,600页的规范,我们不可能在很短的实践中全部都掌握了。可以结合自己项目中用到的具体开发内容,有选择的学习,但首先一定要知道EJB 2.0规范中的具体内容。
有的放矢
循序渐进,有了这种过程,你每次看EJB 2.0规范过程中会有新的领悟。孔子总结出来的道理。比如,我刚王成一个项目,其中的消息驱动Beans用得比较多,所以结合这些内容把EJB 2.0规范中相应的内容多多研究。
再者,需要您去多看看Enterprise JavaBeans API Reference。这些文档可以去Java网站下载。在Mastering EJB中有详细介绍。
-------------------------------------------------------------
EJB常见的开发模式
-------------------------------------------------------------本文的应用服务器以WebLogic为例,其他的服务器过程差不多。
在基于J2EE平台中,EJB的开发属于重中之重。本文试着从几方面,讲述了常用的开发模式和方法。无论是给初学者,还是有经验的朋友都有一定的参考价值。
大家知道,EJB对于初学者来说是一个很头疼的问题,无论是开发还是发布、测试,尤其是Entity Beans更为头疼,所以本文介绍几种用于设计、开发、测试的方法,以供参考。
WebLogic平台,作为业界优秀的产品,其本身提供了很多优秀的工具来开发、发布J2EE应用程序。除此之外,和其他集成开发环境,比如JBuilder、VisualCafe以及支持软件开发整个过程的Together ControlCenter。有了业界这样一种方式的支持,使得WebLogic平台的应用更为广泛。
第一种方式:
用一般的软件开发EJB,比如JCreator、EditPlus都可以。对于初学者,用这种方式比较好,能够对EJB的机制有较为深入的了解。编写完后,把所有的EJB源文件放置在一个src的目录下,并在当前目录(和src目录平行)下建立一个目录deployment,并将写好的配置描述文件ejb-jar.xml和weblogic-ejb-jar.xml拷贝目录deployment下。然后你可以将下面的批处理文件拷贝到目录src的父目录中,然后运行批处理文件。(当然,你需要在这之前设置classpath和相关变量,自己推敲以下就知道了)
//用于编译打包EJB的批处理文件compilejar.bat:
mkdir classes
mkdir lib
mkdir classes\META-INF
copy deployment\*.xml classes\META-INF
javac -d classes src\*.java
cd classes
jar cf ..\lib\temp.jar *
cd ..
cd lib
java weblogic.ejbc -keepgenerated temp.jar xxxEJB.jar
del temp.jar
cd ..
//最终,我们得到了XXXEJB.jar,也就是可以用来直接在WebLogic中发布的jar文件
其中编译EJB我们用到weblogic.ejbc,老版本的WebLogic用的是weblogic.ejbc20。(注: WebLogic中EJB的编译是预编译,也就是说会生成EJB所需的所有的目标文件,但有些应用服务器不是这样的,比如JBoss借助于反射机制在运行期动态生成!)
我们从而得到了xxxEJB.jar,发布到WebLogic上。如果不借助于其他工具,只用WebLogic自己的辅助工具的话,有两种方式可以选择。其一,通过Console台,这种方式最简单了,您应该大体上知道如何弄了。其二,通过WebLogic提供的startWLBuilder.cmd工具。启动后首先要连接到WebLogic中,如图1(图略)所示。步骤是主菜单-〉Tools-〉Connect to Server。
然后连接上服务器后,打开要deploy的EJB,或者Web Application。然后就可以发布了。这两种办法都可以。当然,个人喜欢第二中,因为它可以检查你的EJB打包是否符合要求,同时你需要修改EJB中的配置描述符都很简单,这种图形化的界面操作很方便,从而大大提高deploy的成功率。
第二种方式:
通过第一种方式,我想您也体会到不少东西。当然,大家会想,这样的一种方式还是比较麻烦,至少需要更换两种工具,不舒服。那好,接下来我们介绍第二种方式。与IDE的集成。通过JBuilder Enterprise提供的集成我们可以更加智能的完成工作。关于JBuilder与WebLogic的集成过程,Borland网站,http://bdn.borland.com/,上有两篇分别介绍JBuilder 6 + WebLogic 6.1和JBuilder 7 + WebLogic 7.0的白皮书。
这种方式的引入,使得J2EE应用程序的开发、发布和测试都是在一个统一的环境下进行的,可以大大提高生产效率,使得开发人员可以更加专注于软件本身。
第三种方式:
现在的开发工具、集成开发环境慢慢的很难和软件前期的需求分析、系统建模联系起来,这也是IDE所面临的困境。比如,JBuilder提供了数量有限的UML图以支持软件产品开发。而作为Together ControlCenter,由于其对软件工程的整个过程支持力度很高,所以慢慢流行起来。
Together ControlCenter中内置的BEA WebLogic Application Server PlugIn使得该支持建模、开发、部署J2EE应用程序的工具获得在WebLogic平台下开发软件的开发人员的青睐。如图2(图略)所示。
该平台支持开发人员在开发阶段更换应用服务器,无论是同一服务器的不同版本,还是不同服务器。
综上所述,本文介绍了3种开发EJB的方式,在实际应用中也是使用的模式,开发者可以根据自己的喜好来选择不同的模式。
参考资料
1. Enterprise JavaBeans, 3rd Edition by Richard Monson-Haefel 个人认为最好的EJB书!
2. Effective Java Programming Language Guide by Joshun Bloch(中文版翻译的不太好,个人观点)
3. Thinking in Java ,2nd Edition by Bruce Eckel(侯捷翻译的中文版也不错)
4. http://www.theserverside.com
5. http://java.sun.com/j2ee/tutorial/1_3-fcs/ Enterprise JavaBeans Technology部分
6. http://www.ejbnow.com/ 很有价值的网站!
7. http://java.sun.com/products/ejb/