java 三层架构 ssh
一个 spring2.5+hibernate3.2+struts2.0 组合框架,使用 spring 的 IoC 来管理应用的 所有
bean,包括 struts2 的 action,充分发挥了 spring 轻量级框架的 优势。
摘 要: 针对当前 Web 应用程序开发面临的问题,结合目前比较流行的开源框架 Spring、
Struts 和 Hibernate,提出了一种开发 J2EE Web 应用的轻量级解决方案,以帮助开发人员
在短期内搭建结构清晰、可复用性好、维护方便的 Web 应用程序。并且,通过案例具体说
明了如何将这一方案应用到实际项目中。
关键词: J2EE MVC Struts Spring Hibernate
大型企业级 Web 应用系统的开发通常要求有一个良好的软件架构、便于协作开发和扩展
升级,而传统的开发模式不能很好地满足这些要求。本文针对当前 Web 应用程序开发面临
的问题,结合目前比较流行的开源框架 SSH(Spring、Struts、Hibernate),提出一种开发
J2EE 企业级 Web 应用的轻量级解决方案,并通过案例具体说明如何将这一方案应用到实
际项目中。
1 框架技术
著名的软件大师 Ralph Johnson 对框架(Framework)进行了如下的定义: 框架是整个系
统或系统的一部分的可重用设计,由一组抽象的类及其实例间的相互作用方式组成[1] 。
框架一般具有即插即用的可重用性、成熟的稳定性以及良好的团队协作性。J2EE 复杂的
多层结构决定了大型的 J2EE 项目需要运用框架和设计模式来控制软件质量。目前,市场上
出现了一些商业的、开源的基于 J2EE 的应用框架,其中主流的框架技术有:基于 MVC 模式
的 Struts 框架和基于 IoC 模式的 Spring 框架以及对象/关系映射框架 Hibernate 等。
1.1 表示层框架 Struts
Struts 是一个在 JSP Model2 基础上实现的 MVC 框架,主要分为模型(Model)、视图
(Viewer)和控制器(Controller)三部分,其主要的设计理念是通过控制器将表现逻辑和业务逻
辑解耦,以提高系统的可维护性、可扩展性和可重用性[2] 。Struts 框架的体系结构如图 1
所示。
下面就图 1 所示的体系结构图分析 Struts 框架中的 MVC 组件。
(1)视图:视图部分主要由 JSP 页面组成,其中没有流程逻辑、业务逻辑和模型信息,
只有标记。Struts 自身包含了一组标记库(TagLib),这也是 Struts 的精华之一,灵活运用它
们可以简化 JSP 页面的代码,提高开发效率。
(2)控制器:Struts 中的 Controller 主要是其自身提供的 ActionServlet。ActionServlet
接收所有来自客户端的请求并根据配置文件(struts-config.xml)中的定义将控制转移到适当
的 Action 对象。
(3)模型:Struts 没有定义具体 Model 层的实现,Model 层通常是和业务逻辑紧密相关
的,有持续化的要求。目前在商业领域和开源世界,都有一些优秀的工具可以为 Model 层
的开发提供便利。
1.2 业务逻辑层框架 Spring
Spring 是一个解决了许多 J2EE 开发中常见问题并能够替代 EJB 技术的强大的轻量级框
架。这里所说的轻量级指的是 Spring 框架本身,而不是指 Spring 只能用于轻量级的应用开
发。Spring 的轻盈体现在其框架本身的基础结构以及对其他应用工具的支持和装配能力。
与 EJB 这种庞然大物相比,Spring 可使程序研发人员把各个技术层次之间的风险降低。
Spring 框架的核心是控制翻转 IoC(Inversion of Control)/依赖注入 DI(Dependence
Injection)机制。IoC 是指由容器中控制组件之间的关系(这里,容器是指为组件提供特定服
务和技术支持的一个标准化的运行时的环境)而非传统实现中由程序代码直接操控,这种将
控制权由程序代码到外部容器的转移,称为“翻转”[3] 。DI 是对 IoC 更形象的解释,即由容
器在运行期间动态地将依赖关系(如构造参数、构造对象或接口)注入到组件之中[3] 。
Spring 采用设值注入(使用 Setter 方法实现依赖)和构造子注入(在构造方法中实现依赖)的机
制,通过配置文件管理组建的协作对象,创建可以构造组件的 IoC 容器。这样,不需要编写
工厂模式、单例模式或者其他构造的方法,就可以通过容器直接获取所需的业务组件。Spring
框架的结构如图 2 所示。
Spring 框架由七个定义明确的模块组成,且每个模块或组件都可以单独存在,或者与其
他一个或多个模块联合实现。Spring Core Container 是一个用来管理业务组件的 IoC 容器,
是 Spring 应用的核心;Spring DAO 和 Spring ORM 不仅提供数据访问的抽象模块,还集成
了对 Hibernate、JDO 和 iBatis 等流行的对象关系映射框架的支持模块,并且提供了缓冲连
接池、事务处理等重要的服务功能,保证了系统的性能和数据的完整性;Sprnig Web 模块
提供了 Web 应用的一些抽象封装,可以将 Struts、Webwork 等 Web 框架与 Spring 整合成
为适用于自己的解决方案。
Spring 框架可以成为企业级应用程序一站式的解决方案,同时它也是模块化的框架,允
许开发人员自由地挑选适合自己应用的模块进行开发。Spring 框架式是一个松耦合的框架,
框架的部分耦合度被设计为最小,在各个层次上具体选用哪个框架取决于开发者的需要。
1.3 数据持久层框架 Hibernate
O/R mapping 技术是为了解决关系型数据库和面向对象的程序设计之间不匹配的矛盾而
产生的。Hibernate 是目前最为流行的 O/R mapping 框架,它在关系型数据库和 Java 对象
之间做了一个自动映射,使得程序员可以以非常简单的方式实现对数据库的操作。Hibernate
工作原理如图 3 所示。
Hibernate 通过对 JDBC 的封装,向程序员屏蔽了底层的数据库操作,使程序员专注于
OO 程序的开发,有助于提高开发效率。程序员访问数据库所需要做的就是为持久化对象编
制 xml 映射文件[4] 。
底层数据库的改变只需要简单地更改初始化配置文件(hibernate.cfg.xml 或者
hibernate.properties)即可,不会对应用程序产生影响。
Hibernate 有自己的面向对象的查询语言 HQL,HQL 功能强大,支持目前大部分主流的
数据库,如 Oracle、DB2、MySQL、 Microsoft SQL Server 等,是目前应用最广泛的 O/R
映射工具。Hibernate 为快速开发应用程序提供了底层的支持。
2 基于 SSH 组合框架的 Web 应用模型设计与实现
2.1 集成 SSH 的新型 J2EE 框架
前面分析了基于 J2EE 的三种框架技术,下面通过集成以上三种框架技术来对传统的
J2EE Web 开发模型加以改进,以形成一种新的、轻量型的 J2EE 架构。
集成 SSH 框架 的系统框架图 如图 4 所示,系统从职责上分为四层:表示层、业务逻
辑层、数据持久层和域模块层。其中使用 Struts 作为系统的整体基础架构,负责 MVC 的分
离,在 Struts 框架的模型部分,利用 Hibernate 框架对持久层提供支持,业务层用 Spring
支持。具体做法是:用面向对象的分析方法根据需求提出一些模型,将这些模型实现为基本
的 Java 对象,然后编写基本的 DAO 接口,并给出 Hibernate 的 DAO 实现,采用 Hibernate
架构实现的 DAO 类来实现 Java 类与数据库之间的转换和访问,最后由 Spring 完成业务逻
辑。
系统的基本业务流程是:在表示层中,首先通过 JSP 页面实现交互界面,负责传送请求
(Request)和接收响应(Response),然后 Struts 根据配置文件 (struts-config.xml)将
ActionServlet 接收到的 Request 委派给相应的 Action 处理。在业务层中,管理服务组件的
Spring IoC 容器负责向 Action 提供业务模型(Model)组件和该组件的协作对象数据处理(DAO)
组件完成业务逻辑,并提供事务处理、缓冲池等容器组件以提升系统性能和保证数据的完整
性。而在持久层中,则依赖于 Hibernate 的对象化映射和数据库交互,处理 DAO 组件请求
的数据,并返回处理结果。
采用上述开发模型,不仅实现了视图、控制器与模型的彻底分离,而且还实现了业务逻
辑层与持久层的分离。这样无论前端如何变化,模型层只需很少的改动,并且数据库的变化
也不会对前端有所影响,大大提高了系统的可复用性。而且由于不同层之间耦合度小,有利
于团队成员并行工作,大大提高了开发效率。
2.2 基于 SSH 框架 的 Web 应用系统的实现
下面将通过一个实际的系统来展示如何进行基于 SSH 框架 的 Web 应用开发。该系统
是为某通信公司运营部开发的一个问答式系统,功能类似于百度知道和新浪爱问。由于系统
的模块较多,下面就以一个用户管理模块为例来说明系统的开发实现过程,并将按照数据持
久层、业务逻辑层、表示层的顺序说明系统构建过程。
(1)数据持久层
数据持久层由 Java 对象持久化类和数据访问对象(DAO)组成。每个数据库表都对应着
一个持久化对象,这样就给予了开发者使用 OO 思想设计和开发的便利,同时也屏蔽了具体
的数据库和具体的数据表、字段,消除了对数据库操作的硬编码在重用性上的弊端。用户信
息表的部分结构如表 1 所示。
Hibernate 通过映射(Mapping)文件将对象(Object)与关系型数据(Relational)相关联,因
此需要编写和数据库表相对应的 Java 持久化类以及对应的映射文件。有了 Java 持久化类后
就可以在此基础上实现数据访问类。在 Spring 框架中,数据访问类可以从辅助类
HibernateDaoSupport 继承,这极大地方便了 Hibernate 框架在 Spring 中的使用,相应的部
分代码如下:
public class UserDao
extends HibernateDaoSupport {
public int add(User user) {
return Integer.ParseInt(this.getHibernateTemplate().save(user).toString());
}
public List findAll() {
return this.getHibernateTemplate().loadAll(User.class);
}
}
具体的 Hibernate 数据源、session 工厂、事务管理、缓冲连接池等功能都由业务层的
Spring 容器提供。
(2)业务逻辑层
业务逻辑层由 Spring 框架支持,提供了处理业务逻辑的服务组件。开发者需要对业务
对象建模,抽象出业务模型并封装在 Model 组件中。由于数据持久层实现了 Java 持久化类
并且封装了数据访问对象(DAO),因此可以在 Model 组件中方便地调用 DAO 组件来存取数
据。Spring 的 IoC 容器负责统一管理 Model 组件和 DAO 组件以及 Spring 所提供的事务处理、
缓冲连接池等服务组件。
在用户管理模块中,通过业务建模创建了用户模型 UserService 类,封装了对用户的权
限管理以及积分管理等功能。UserService 类通过调用数据访问类 UserDao 实现对用户数据
的操作。这些组件的关系将通过配置 Spring 框架的 applicationContext.xml 联系起来,配置
文件的主要内容如下:
(3)表示层
表示层结合 JSP 和 Struts 的 TagLib 库处理显示功能,利用 ActionServlet 将请求(*.do)
映射到相应的 Action,并由 Action 调用业务逻辑的服务组件,然后根据处理结果跳转到
Forword 对象指定的响应页面。
业务流程的部署由 struts-config.xml 完成。下面以一个显示所有用户信息的请求
(ListUser.do)为例来说明配置文件的使用。
基于 J2EE 的 Web 应用以其层次性、平台无关性的优势已经逐渐成为了电子商务、电子
政务主要的解决方案。本文针对传统的 J2EE Web 应用开发的弊端,提出了一种利用轻量级
框架来快速搭建 Web 应用的解决方案,并且通过其在实际项目中的应用,证明了采用此方
案可以帮助开发人员在短时间内建立结构清晰、可重用性好、维护扩展方便的 Web 应用程
序。
参考文献
[1] GAMMA E, HELM R, JOHNSON R, et al. Design patterns:Elements of reusable
object-oriented software[M]. Addison Wesley, 1994.
[2] 孙卫琴.精通 Struts:基于 MVC 的Java Web 设计与开发[M]. 北京:电子工业出版社,2004.
[3] JOHNSON R, HOELLER J, ARENDSEN A, et al. Java/J2EE application framework
reference document. V1.1.
2004.
[4] 徐长盛,戴超.一种快速开发 Web 应用程序方法的研究[J]. 计算机工程与设
计,2004,(12):2237-2239.
[5] 夏昕,曹晓钢,唐勇.深入浅出 Hibernate[M]. 北京:电子工业出版社,2005.
[6] JOHNSON R.Expert one-on-one J2EE design and development[M]. 魏海萍译.北京:
电子工业出版社,2003.
在用 ssh 开发 web 应用时,需要对生成的 各个类文件进行组织,下面就对一个可行的 目
录方案进行介绍:
譬如应用中有一个用户管理模块,则在公共包下建立一个 user 包,如该公共包可以为
com.simon.oa,
在 user 包下包括如下子包
1、controler 包
该包放置各种 struts 的 action。
2、dao 包
该包放置各类 dao(data access object),也就是放置对数据库访问的 实现类,在用 myeclipse
中的 “Hibernate Reverse Engineering”进行反向操作时在某一个目录中就会生成对应某个
表的 DAO,生成后可将该 DAO 拖到 dao 包中。在某些应用中将 DAO 作为接口,在该接口
中包括所有对数据库的 操作方法,然后在 dao 包建立一个 hibernate 包,在 hibernate 包中
放置对 DAO 接口的 实现,譬如:UserDAO 接口有一个实现类为 UserDaoImpl,将该类放置
到 hibernate 包中,实际的 开发倾向于后一种方式,因为对这个 DAO 接口可以实现 spring
的 IoC 操作。(不知道 myeclipse 对此是怎么考虑的 ,这个问题让我纠缠了很久,误将 DAO
理解成一个能够进行实际操作的 类,而不是一个接口,以后开发要注意 )
3、model 包
该包中放置 hibernate 反向工程生成的 bean 和该 bean 对应的 .hbm.xml 文件。
4、service 包
该包放置业务操作类,譬如用户服务类,一般情况将该用户操作类提取一个接口,然后在
service 包下生成一个 impl 包,在 impl 包中才放置用户操作接口的 实现类。该用户接口实
现类中调用 DAO 接口对数据库进行操作,而调用该实现类的 方法在 struts 的 action 中。
5、vo 包(value object)
vo 包中的 中包括 struts 中使用的 POJO 及 actionform 等信息。
VO: Value Object
DTO: Data Transfer Object
个人理解 VO 和 DTO 是类似的 东西,原则上 VO 和 DTO 只有 Public Fields,主要用于进程
之间数据传递的 问题,VO 和 DTO 不会传递到表示层,在业务层就会被吸收。但看到很多
人在建立 VO 和 DTO 时,也含有 Setter,Getter 属性和一些其它的 辅助方法,这也无可厚非,
我自己也不能确定这对不对。