Struts+Spring+Hibernate组装web应用
2008-01-05 19:56:40 来源:WEB开发网核心提示:摘要:这篇文章将讨论怎样组合几个闻名的框架去做到松耦合的目的,怎样建立你的构架,Struts+Spring+Hibernate组装web应用,怎样让你的各个应用层保持一致,富于挑战的是:组合这些框架使得每一层都以一种松耦合的方式彼此沟通,准确的包命名为你的类提供的功能提供一个清楚的区分,使当故障维护时更易于维护,而与底
摘要:
这篇文章将讨论怎样组合几个闻名的框架去做到松耦合的目的,怎样建立你的构架,怎样让你的各个应用层保持一致。富于挑战的是:组合这些框架使得每一层都以一种松耦合的方式彼此沟通,而与底层的技术无关。这篇文章将使用3种流行的开源框架来讨论组合框架的策略
其实,就算用java建造一个不是很烦琐的web应用程序,也不是件轻松的事情。当为一个应用程序建造一个构架时有许多事情需要考虑。从高层来说,开发者需要考虑:怎样建立用户接口?在哪里处理业务逻辑?和怎样持久化应用数据。这三层每一层都有它们各自的问题需要回答。 各个层次应该使用什么技术?怎样才能把应用程序设计得松耦合和能灵活改变?构架答应层的替换不会影响到其它层吗?应用程序怎样处理容器级的服务,比如事务处理?
当为你的web应用程序创建一个构架时,需要涉及到相当多的问题。幸运的是,已经有不少开发者已经碰到过这类重复发生的问题,并且建立了处理这类问题的框架。一个好框架具备以下几点: 减轻开发者处理复杂的问题的负担(“不重复发明轮子”);内部定义为可扩展的;有一个强大的用户群支持。框架通常能够很好的解决一方面的问题。然而,你的应用程序有几个层可能都需要它们各自的框架。就如解决你的用户接口(UI)问题时你就不应该把事务逻辑和持久化逻辑掺杂进来。例如,你不应该在控制器里面写jdbc代码,使它包含有业务逻辑,这不是控制器应该提供的功能。它应该是轻量级的,代理来自用户接口(UI)外的调用请求给其它服务于这些请求的应用层。好的框架自然的形成代码如何分布的指导。更重要的是,框架减轻开发者从头开始写像持久层这样的代码的痛苦,使他们专注于对客户来说很重要的应用逻辑。
这篇文章将讨论怎样组合几个闻名的框架去做到松耦合的目的,怎样建立你的构架,怎样让你的各个应用层保持一致。富于挑战的是:组合这些框架使得每一层都以一种松耦合的方式彼此沟通,而与底层的技术无关。这篇文章将使用3种流行的开源框架来讨论组合框架的策略。表现层我们将使用Struts;业务层我们将使用SPRing;持久层使用Hibrenate.你也可以在你的应用程序中替换这些框架中的任何一种而得到同样的效果。图1展示了当这些框架组合在一起时从高层看是什么样子。
图1 用Struts, Spring, 和 Hibernate框架构建的概览
应用程序的分层
大多数不复杂的web应用都能被分成至少4个各负其责的层次。这些层次是:表现层、持久层、业务层、领域模型层。每层在应用程序中都有明确的责任,不应该和其它层混淆功能。每一应用层应该彼此独立但要给他们之间放一个通讯接口。让我们从审阅各个层开始,讨论这些层应该提供什么和不应该提供什么。 QQread.com 推出各大专业服务器评测 linux服务器的安全性能 SUN服务器 HP服务器 DELL服务器 IBM服务器 联想服务器 浪潮服务器 曙光服务器 同方服务器 华硕服务器 宝德服务器 表现层
在一个典型的web应用的一端是表现层。很多Java开发者也理解Struts所提供的。然而,太常见的是,他们把像业务逻辑之类的耦合的代码放进了一个org.apache.struts.Action。所以,让我们在像Struts这样一个框架应该提供什么上取得一致意见。这儿是Struts负责的:
·为用户治理请求和响应;
·提供一个控制器代理调用业务逻辑和其它上层处理;
·处理从其它层掷出给一个Struts Action的异常;
·为显示提供一个模型;
·执行用户接口验证。
这儿是一些经常用Struts编写的但是却不应该和Struts表现层相伴的项目:
·直接和数据库通讯,比如JDBC调用;
·业务逻辑和与你的应用程序相关的验证;
·事务治理;
·在表现层中引入这种代码将导致典型耦合和讨厌的维护。
持久层
在典型web应用的另一端是持久层。这通常是使事情迅速失控的地方。开发者低估了构建他们自己的持久层框架的挑战性。一般来说,机构内部自己写的持久层不仅需要大量的开发时间,而且还经常缺少功能和变得难以控制。有几个开源的“对象-关系映射”框架非常解决问题。尤其是,Hibernate框架为java提供了"对象-关系持久化"机制和查询服务。Hibernate对那些已经熟悉了SQL和JDBC API的Java开发者有一个适中的学习曲线。Hibernate持久对象是基于简单旧式Java对象和Java集合。此外,使用Hibernate并不妨碍你正在使用的IDE。下面的列表包含了你该写在一个持久层框架里的代码类型:
查询相关的信息成为对象。Hibernate通过一种叫作HQL的面向对象的查询语言或者使用条件表达式API来做这个事情。 HQL非常类似于SQL-- 只是把SQL里的table和columns用Object和它的fields代替。有一些新的专用的HQL语言成分要学;不过,它们轻易理解而且文档做得好。HQL是一种使用来查询对象的自然语言,花很小的代价就能学习它。
保存、更新、删除储存在数据库中的信息。
像Hibernate这样的高级“对象-关系”映射框架提供对大多数主流SQL数据库的支持,它们支持“父/子”关系、事务处理、继续和多态。
这儿是一些应该在持久层里被避免的项目:
业务逻辑应该在你的应用的一个高一些的层次里。持久层里仅仅答应数据存取操作。
你不应该把持久层逻辑和你的表现层逻辑搅在一起。避免像jsps或基于servlet的类这些表现层组件里的逻辑和数据存取直接通讯。通过把持久层逻辑隔离进它自己的层,应用程序变得易于修改而不会影响在其它层的代码。例如:Hebernate能够被其它持久层框架或者API代替而不会修改在其它任何层的代码。
业务层
在一个典型的web应用程序的中间的组件是业务层或服务层。从编码的视角来看,这个服务层是最轻易被忽视的一层。不难在用户接口层或者持久层里找到散布在其中的这种类型的代码。这不是正确的地方,因为这导致了应用程序的紧耦合,这样一来,随着时间推移代码将很难维护。幸好,针对这一问题有好几种Frameworks存在。在这个领域两个最流行的框架是Spring和PicoContainer,它们叫作微容器,你可以不费力不费神的把你的对象连在一起。所有这些框架都工作在一个简单的叫作“依靠注入”(也通称“控制反转”)的概念上。这篇文章将着眼于Spring的为指定的配置参数通过bean属性的setter注入的使用。Spring也提供了一个构建器注入的复杂形式作为setter注入的一个替代。对象们被一个简单的xml文件连在一起,这个XML文件含有到像事务治理器、对象工厂、包含业务逻辑的服务对象、和数据存取对象这些对象的引用。
这篇文章的后面将用例子来把Spring使用这些概念的方法说得更清楚一些。业务层应该负责下面这些事情:
·处理应用程序的业务逻辑和业务验证;
·治理事务;
·预留和其它层交互的接口;
·治理业务层对象之间的依靠;
·增加在表现层和持久层之间的灵活性,使它们互不直接通讯;
·从表现层中提供一个上下文给业务层获得业务服务;
·治理从业务逻辑到持久层的实现。
领域模型层
最后,因为我们讨论的是一个不是很复杂的、基于web的应用程序,我们需要一组能在不同的层之间移动的对象。领域对象层由那些代表现实世界中的业务对象的对象们组成,比如:一份订单、订单项、产品等等。这个层让开发者停止建立和维护不必要的数据传输对象(或者叫作DTOs),来匹配他们的领域对象。例如,Hibernate答应你把数据库信息读进领域对象的一个对象图,这样你可以在连接断开的情况下把这些数据显示到UI层。那些对象也能被更新和送回到持久层并在数据库里更新。而且,你不必把对象转化成DTOs,因为DTOs在不同的应用层间移动,可能在转换中丢失。这个模型使得Java开发者自然地以一种面向对象的风格和对象打交道,没有附加的编码。
结合一个简单的例子
既然我们已经从一个高的层次上理解了这些组件, 现在就让我们开始实践吧。在这个例子中,我们还是将合并Struts、Spring、Hibernate框架。每一个这些框架在一篇文章中都有太多的细节覆盖到。这篇文章将用一个简单的例子代码展示怎样把它们结合在一起,而不是进入每个框架的许多细节。示例应用程序将示范一个请求怎样跨越每一层被服务的。这个示例应用程序的一个用户能保存一个订单到数据库中和查看一个在数据库中存在的订单。进一步的增强可以使用户更新或删除一个存在的订单。
因为领域对象将和每一层交互,我们将首先创建它们。这些对象将使我们定义什么应该被持久化,什么业务逻辑应该被提供,和哪种表现接口应该被设计。然后,我们将配置持久层和用Hibernate为我们的领域对象定义“对象-关系”映射。然后,我们将定义和配置我们的业务对象。在有了这些组件后,我们就能讨论用Spring把这些层连在一起。最后,我们将提供一个表现层,它知道怎样和业务服务层交流和知道怎样处理从其它层产生的异常。
领域对象层
因为这些对象将和所有层交互,这也许是一个开始编码的好地方。这个简单的领域模型将包括一个代表一份订单的对象和一个代表一个订单项的对象。订单对象将和一组订单项对象有一对多的关系。例子代码在领域层有两个简单的对象:
·com.meagle.bo.Order.java: 包括一份订单的概要信息;
·com.meagle.bo.OrderLineItem.java: 包括一份订单的具体信息;
考虑一下为你的对象选择包名,它将反映你的应用程序是怎样分层的。例如:简单应用的领域对象可以放进com.meagle.bo包。更多专门的领域对象将放入在com.meagle.bo下面的子包里。业务逻辑在com.meagle.service包里开始打包,DAO对象放进com.meagle.service.dao.hibernate包。对于forms和actions的表现类分别放入com.meagle.action 和 com.meagle.forms包。准确的包命名为你的类提供的功能提供一个清楚的区分,使当故障维护时更易于维护,和当给应用程序增加新的类或包时提供一致性。
- ››Hibernate高级应用:性能优化策略
- ››hibernate 多对多关系详解(包括中间表,一对多字表...
- ››Spring源码学习-含有通配符路径解析(上)
- ››Hibernate实现mysql数据库limit查询方法
- ››Struts2配置文件中redirect传递中文参数乱码的解决...
- ››Spring MVC与JAX-RS比较与分析
- ››Spring 框架的设计理念与设计模式分析
- ››Spring Web Flow 2 中流管理的持久化
- ››Spring 事务管理高级应用难点剖析: 第 2 部分
- ››Spring 事务管理高级应用难点剖析: 第 3 部分
- ››Spring 事务管理高级应用难点剖析,第 1 部分
- ››StrutsTestCase 简化开发过程
更多精彩
赞助商链接