随着Internet的飞速发展,B/S应用系统的需求量在不断增多,对快速开发Web应用系统的要求也越来越强烈! 然而,在实践过程中我们也经常面临这样的问题:如何快速搭建Web应用系统的框架?如何提高系统的可维护性、可复用性、可扩展性以及安全性?如何整合优化现有的优秀的Web应用框架技术,从而以更小的成本、更少的资源、更快地完成应用的设计和开发?
本文以开源项目Struts[1]、Tiles[2]、Log4j[2]以及Hibernate[3]等优秀的应用框架为基础,结合JSP技术和MVC2设计思想,给出了一个结构清晰、可扩展性良好、复用性高、维护简便的Web应用开发框架。
1 Web应用框架
框架是一种应用系统的部分或整体的可复用设计,框架具体表现为一组抽象构件类及其实例(对象)之间的相互作用[4] 。框架蕴涵特定领域的体系结构设计以及解决策略,并经实践检验是可复用的。系统设计者有选择地重用、扩展这些框架来构建特定的应用。下面简要介绍本文涉及的Web应用框架。
1.1 Tiles介绍
Tiles是Apache基金会的开放源码项目,现已成功集成到Struts框架。Tiles框架为创建Web页面提供了一种模版机制,它能够动态地将内容插入到模版,实现了页面的布局和内容分离。此外支持视图的继承和重载,共享了父视图中对于布局的定义,极大地减少了复合视图的代码量,充分体现了面向对象的设计理念。
1.2 Struts介绍
Struts是Apache基金会Jakarta项目下的开放源码项目,是基于MVC2模式的Web应用框架。目前的版本是1.2.4。Struts不仅仅是一个强大的框架,同时它也是可扩展的。可以通过以下几种方式来扩展Struts:
1) 实现PlugIn:通过实现org.apache.struts.action.PlugIn接口,在应用启动和关闭时处理一些业务逻辑。 比如初始化Hibernate配置,关闭Hibernate等;
2) 继承RequestProcessor:通过继承org.apache.struts.action.RequestProcessor类,可以在请求被处理的过程中的某个时刻做一些业务逻辑。比如说,在每次请求执行之前,扩展RequestProcessor来检查用户是否登陆以及是否有权限去执行某个特定的action;
3) 扩展ActionServlet:通过扩展org.apache.struts.action.ActionServlet类可以在应用启动和关闭时以及请求被处理时做一些特定的业务逻辑;
4) 扩展Action:扩展org.apache.struts.action.Action类处理一些公共逻辑代码,从而减少代码冗余。
Struts自身集成了Validation和Tiles框架,通过绑定资源文件,在错误处理、数据验证、页面布局设计以及国际化方面提供了良好的解决方案;此外它可以无缝结合JSTL、自定义标签(Custom Tag),从而几乎杜绝了JSP中的java代码,实现视图层和业务逻辑层的解耦,同时提高了系统的可维护性。
1.3 Log4j介绍
Apache基金会Jakarta项目下的开放源代码Log4j子项目,是一个日志操作包。通过配置文件,灵活地指定日志消息输出的目的地,并可以控制每一条日志的输出格式。此外,通过定义日志消息的级别,能够非常细致地控制日志的输出。
1.4 J2EE平台EJB技术[6]
EJB技术实现对业务逻辑的封装和应用的分布式处理。
1.5 Hibernate介绍
Hibernate是一项开源的对象/关系数据库映射(Object/Relationship Mapping(ORM))技术,用来把对象模型表示的对象映射到基于SQL 的关系模型结构中去。目前发布的最新产品版本是3.0,并提供了3.0.1的测试版。鉴于Hibernate成功应用,EJB专家组在重新设计EJB3.0的Entity Beans时从Hibernate中吸取了多个关键的理念和APIs[5]。
图1显示了Hibernate的核心APIs概览,包括:
1) 供应用调用完成基本CRUD(Create、Read、Update、Delete)和查询操作的接口,如Session,Transaction以及Query;
2) 应用系统配置Hibernate的接口,如Configuration类;
3) 回调接口使得应用系统能够同Hibernate内部的事件交互,如Interceptor,Lifecycle和Validatable接口;
4) Hibernate充分利用现有的Java APIs,包括JDBC,Java Transaction API(JTA)以及Java Naming and Directory(JNDI)接口。JDBC为关系数据库抽象出了公共的功能,只要通过JDBC驱动,Hibernate几乎支持所有的数据库;JNDI和JTA使得Hibernate可以同J2EE应用服务器交互。
此外,Hibernate还提供了以下扩展点:
1) 实现IdentiferGenerator接口:为应用实现主键生成策略;
2) 扩展Dialect抽象类:支持独立的SQL方言;
3) 实现Cache和CacheProvider接口:提供自定义的缓存策略;
4) 实现ConnectionProvider接口:自管理JDBC连接;
5) 实现TransactionFactory,Transaction,TransactionManagerLookup接口:事务管理;
6) 实现ClassPersister接口:对象关系映射策略;
7) 实现PropertyAccessor接口:提供属性访问策略;
8) 实现ProxyFactory接口:Proxy创建方法。
图 1 多层架构下Hibernate API 概览
Figure 1 High-level overview of the HIbernate API in a layered architecture
图 2 非被管理环境(Servlet容器)中使用JDBC连接池(未使用Hibernate)
Figure 2 JDBC connection pooling in a non-managed environment
图3 非管理环境(Servlet容器)下的Hibernate应用 Figur 3 Hibernate with a connection pool in a non-managed environment
|
图4 管理环境(EJB容器)下的Hibernate应用 Figure 4 Hibernate in a managed environment with an application server
|
图2是未使用Hibernate的典型情况,需要开发人员自己管理JDBC连接,熟悉各种数据库的操作,底层数据库改变将直接影响整个应用系统的改动;而图2和图3显示了Hibernate在非管理环境(Servlet容器)和管理环境(J2EE应用服务器)下的应用。非管理环境和管理环境的差别就在于容器是否提供应用系统安全(授权和认证)、连接池以及事务管理。
从图3可以看出,Hibernate相当于是JDBC连接池的客户端,向开发人员屏蔽了底层的数据库操作,开发人员只需为持久化对象配置xml文件,从而专注于面向对象的开发。即使底层数据库改变了也只要简单修改初始化配置文件(hibernare.properties或hibernate.cfg.xml)。在我校的博士论文评阅系统中采用了图3所示的策略。
图 4 则反映了应用系统通过会话 Beans 或消息驱动 Beans 来调用 Hibernate APIs 的情况, Hibernate 相关的所有代码在非管理和管理环境下是完全适用的。通常在大型分布式应用中采用图 4 的策略。