订阅信息系统
本章通过订阅信息系统的设计和开发,介绍EJB在实践项目中的应用。当一个J2EE项目达到一定的规模,Web层和EJB层中很多类要进行频繁地交互操作。如果设计一种Web层与EJB层通用接口框架,在配置文件中设定Web层和EJB层中执行类的对应关系。这样就能完成两个大层次之间松散而且快速的联系,实现J2EE项目可动态扩展。在本章也将介绍这种接口框架系统的设计和使用
5.1 需求分析
5.2 架构设计
EJB作为一种成熟的分布式对象组件技术,已经得到越来越广泛的应用,EJB已经成为了一种事实上的工业标准。它允许在一个供应商的EJB服务器上开发和部署的Bean能轻易地部署到其他供应商的EJB服务器上。最重要的是:开发EJB时已经不用考虑有关负载平衡、事务安全性等复杂的跨服务器技术,这些技术已经由EJB容器服务器实现,只要将具体的EJB
Bean部署到EJB服务器中,经过适当简单的配置,开发者自己的应用系统就可以成为一个分布式的、集群的网络系统,这样使得开发大访问量的应用系统项目不再成为少数大型公司的专利。
5.2.1 Cache和Pool
在J2EE项目开发中,包括本项目,都会将重要的业务逻辑运算封装在EJB层,Web层只是作为EJB的一种客户端。这种设计安排已经不同于之前在JSP/Javabeans下的思路,在以前JSP/Javabeans框架下,业务逻辑运算等重要功能都是在Javabeans实现。但是随着应用系统访问用户的不断增长,系统的性能需要不断提高,提高性能方式有很多,主要思路是使用Cache(缓冲)和Pool(池)机制。
如果使用EJB,那么上述那些Cache或Pool、事务机制、安全访问权限以及分布式运算等都无需再考虑了,所有这些都将由EJB容器来完成。
5.2.2 EJB框架体系
在EJB中有两种类型:无状态Session Bean(Stateless session bean)和有状态Session
Bean(Stateful session bean)。EJB容器使用Cache或Pool机制来支持EJB运行。
有状态Session Bean实际是运行在EJB容器的Cache中;而无状态Session Bean则是运行在EJB容器的Pool中。
5.2.3 架构图
5.2.4 接口框架设计
在本项目中,将建立一个通用的Web和EJB接口框架,实现图5-4中Web层与EJB层之间的统一通道。这种框架实现了两个容器之间的解耦,同时又使得Web层对EJB层的调用变得标准而有规则,可以推广应用到大多数J2EE项目中。
框架的优点:
可重用性强,使用方便。由于形成了一个标准框架,在具体应用中只要分别实现相应接口就可以直接使用该框架。
松散的耦合性。与Web层和EJB层都保持了松散的耦合性,同时为两者之间联系提供了一个可控制的通道。
易于开发,该框架好似一根扁担,一头挑起了Web层,另外一头挑起了EJB层,使得整个J2EE的开发分工明确。负责Web层程序开发的Team只要做好与框架的接口工作,而负责EJB层程序开发的Team做好与框架接口另外一边,再通过配置文件配置,就可以将整个J2EE系统轻松地组合运行起来。
易于拓展,可以在这个框架中很方便地加入缓冲Cache,这样减少Web层对EJB层的频繁访问。
5.3 EJB详细设计和实现
5.3.1 业务对象建模
5.3.2 开发环境配置
目前,使用JBoss 3.0 作为应用服务器,MySQL 4.0作为数据库,JBuilder作为编程工具和Rose作为设计工具的J2EE设计开发运行模式已经日趋成熟稳定。其显著特点是打破了J2EE成本居高不下的弊端,以极其低廉的运行成本受到广大用户的欢迎。
尤其是JBoss作为免费的J2EE服务器,对webshere和weblogic商业服务器形成了有力的冲击。SQL
4.0在继承以前版本快速稳定的基础上,整合了InnoDB (http://www.InnoDB.com/)先进的事务处理机制,从最近关于MySQL伴随Linux不断蚕食商业数据库市场的报道中,可以预见MySQL辉煌的未来。
EJB的开发如果完全手工编码是非常繁琐的,当然需要依靠强大的IDE工具来达到快速开发的目的,JBuilder作为快速有力的开发工具,其独特性主要表现在7.0以后版本提供的EJB快速可视化开发功能。
跟随最新技术版本新的开发环境请按这里。
5.3.3 CMP图形开发
5.3.4 实体Bean
5.3.5 Facade Session Bean
Facade模式可以在客户端和EJB之间建立一个统一接口,客户端只要直接和Facade类交互操作,通过Facade类再操作那些实体Bean,如图5-12所示。
5.3.6 Transfer Object 模式
客户端Web层向EJB层发出的调用无非是两个方面:数据和有关数据功能操作。前面章节已经通过Facade模式统一了有关数据功能操作的封装。在本节,将讨论数据本身的统一封装问题。
在实际项目中,客户端所要求数据项目也可能是多个的。例如,如果在客户端要显示一个客户的城市、街道等详细地址,那么是不是分别通过EJB查询数据库?如果每个数据项都分别操作一次EJB,那这种情况又类似于客户端直接操作实体Bean,带来的危害是增加了网络操作负担,降低了性能。
5.4 WEB与EJB接口框架
了避免在大项目中Web层和EJB层过分耦合,提高Web层和EJB层的开发效率,加强J2EE系统的可维护性和可拓展性,需要在Web层和EJB层之间建立一个类似接口网关的框架系统,这样可以适应推广在各个J2EE项目中。
5.4.1 框架的设计
在本项目中,由于使用了CustomerManager代表实体Bean的统一接口,这样客户端可以直接调用CustomerManager了。在本项目中这个客户端位于Web容器中,是Strut的一个Action,以CustomerAction为例,它负责处理前台JSP提交的表单数据,经过简单封装,然后递交到EJB层进行“深加工”
在CustomerAction中实现了对EJB的调用,这种将EJB调用直接嵌入Action中有很多缺点:
加重网络负担。如果在CustomerAction一个方法体内分别调用多个不同的Facade类,就类似客户端直接调用实体Bean的问题,大大加重了网络传输负担。
可维护性差。如果在CustomerAction再增加editCustomer等其他方法,CustomerAction就变得复杂,导致维护性和拓展性降低。
与Web层过分耦合。Action属于Strut的一个部分,这样造成整个系统严重依赖Strut,如果将来有新的客户端(非HTML等),Strut框架不能使用的情况下,需要对系统Web层进行较大改动。
与EJB层过分耦合。由于在Action代码中直接指定了EJB调用代码。如CustomerAction中直接指定了EJB CustomerManager作为逻辑运算的进一步处理。但是在一个大型系统中,这种情况随时会发生改变。如其他Team由于开发了新的客户EJB组件,那么就需要直接修改CustomerAction代码。
针对这些缺点,首先采取分离措施,将EJB访问调离Action类。这样在前台表现层和EJB层之间形成了一个新的Proxy层。
这些优点都从PetStore源码中可以发现,以用户资料修改为例,CustomerEvent通过WebController触发了EJBControllerLocal,而EJBControllerLoca委托状态机StateMachine读取配置文件eventmappings.xml调用相应的Action类进行处理,CustomerEvent对应的Action类是CustomerEJBAction,CustomerEJBAction是一个普通的Javabean,即处理CustomerEvent是由EJB委托普通Javabean来实现真正的逻辑运算,如创建新的客户资料。
这里有一个明显的缺点,事务处理机制粗糙。因为创建新客户资料每一句代码是在Javabean中实现,而不是在正常的session bean实现,因此不能实现方法体内的事务机制。
5.4.2 框架的实现
在该框架中,比较重要的核心类是ServiceProxy类。在该类中要做到一个接口的作用,承前启后,同时又不能与前后过分耦合,这是通过两种方式达到的:首先通过XML配置文件和Web层建立对应关系,这样是可扩展而且安全的;然后通过JNDI调用EJB层的一个Facade总类,这个Facade总类在具体应用系统中是可以定义的。
5.4.3 框架的使用
该框架比较方便,只要完成三步就可以:首先,将基本对象包装成Event事件;其次,实现ServiceProxy;最后,配置ServiceProxy和前台Action的对应表eventmappings.xml。
5.5 表现层的设计和实现
上节中已经实现了Struts的Action类CustomerAction,这里将在Struts框架进行其他的操作步骤,JBuilder
8/JBuilderX以后版本整合了Strut框架,因此利用JBuilder提供的可视化开发可以提高速度。
5.5.1 创建ActionForm
5.5.2 创建Action类
Action类主要是接受处理前台表单输入的数据,CustomerAction代码已经在前面章节罗列出,该Action类有两个步骤:
将CustomerForm中的数据导入CustomerDTO,CustomerForm中数据是JSP页面用户输入的值。
将CustomerDTO对象传送访问EJB层,实现customer数据的插入数据库操作。
CustomerAction处理成功后,将页面导向createCustomOk页面,这就需要在struts-config.xml中配置createCustomOk指向的页面。
5.5.3 创建Jsp页面
5.6 调试 配置和运行
EJB层和Web层开发完成后,可以进行各自的单元测试。通过使用JBuilder等IDE工具提供的EJB Test工具可以直接建立一些客户端对EJB实现测试。当然,EJB需要部署到EJB容器中才能运行,而各个EJB容器在遵循J2EE标准的总体框架下有些细微的区别。
本项目使用JBoss作为J2EE服务器,MySQL作为数据库服务器。目前需要对这两者进行配置,使得JBoss具备访问MySQL数据库的能力。
5.6.1 JBoss和MySQL的配置
各个版本JBoss和MySQL的配置有些细节的区别,总体可以掌握下列几点。
5.6.2 JNDI配置
在JBoss中部署J2EE应用程序,其EJB的配置文件共有3个:ejb-jar.xml、jboss.xml和jbosscmp-jdbc.xml,这些配置是将程序代码系统和容器服务器联系在一起的纽带。
其中最关键的,也是比较复杂的是有关JNDI和EJB引用reference的对应关系设置。因为EJB是分布式的,所以并没有按照一般思维习惯直接将JNDI和EJB对应起来,而是在JNDI和EJB之间加入了一个EJB引用reference,这样整个系统做到了灵活部署,但是也增加了复杂性。
5.6.3 部署和发布
由于本项目包括Web层和EJB层,相应的文件是.war和.jar,可以将这两个文件直接复制到JBoss/server/default/deploy下。如果把这两个文件打包成一个.ear文件,部署起来可能更方便。
通过JBuilder可以迅速建立一个EAR包,选择new →Enterprise的EAR,将需要的Web包和EJB包加入,如果需要其他EJB组件,也可以在这里一起加入。Rebuilder整个项目将生成如CmpSUB.ear这样的发布包,直接复制到JBoss/server/default/deploy下。这时会注意到JBoss控制台进行EAR发布的信息,分别部署其中的EJB和Web。
5.6.4 调试和测试
这时可以进入系统整合测试,整合测试相比部署时出现的问题更多。这时需要依靠Logger的日志输出,或者依赖Junit单元测试。个别按照正常逻辑不可思议发生的问题,可以使用JBuilder的断点调试功能追踪系统中实际运行的路线,可能发现一些潜在的问题。
这里有一些调试经验供参考:
5.7 小结
EJB的实战应用和其理论相差比较大,本章主要是通过一个小型的订阅信息系统介绍了EJB相关实战知识。
对于有丰富JavaBeans开发经验的程序员来说,JavaBeans应用基本分两大类:功能JavaBeans和数据JavaBeans。前者是实现一定功能的,有一定行为的JavaBeans;而后者则只是包含数据的、没有功能的JavaBeans。这也是通常说的Transfer
Object、Value Object或者POJO(无格式普通Java 对象,英文是Plain Old Java Object)。
|