用java来徏立一个很有h(hun)值的web 应用不是一个简单的d。在架构q个应用时要考虑很多的因素和问题。从更高的层ơ来看,开发h员面临着关于如何构徏用户接口Q何处驻留业务逻辑Q以?qing)如? 实现数据持久性这些问题。这3层都有各自的问题需要回{。而每一层又需要实现那些技术?应用如何设计来进行松散耦合q能q行灉|变更Q应用架构是否允许某 一层变更而不影响到其它的层次Q应用应该如何处理容器一U的服务比如事务Q?/p>
在ؓ(f)你的应用创徏一个架构之前有许多问题需要澄清。幸q的是,有很多开发者都意识到这个问题,q徏立了(jin)很多框架来解册些问题。一个良好的框架可以 让开发h员减轻重新徏立解军_杂问题方案的负担和精力;它可以被扩展以进行内部的定制化;q且有强大的用户C来支持它。框枉常能很好的解决一个问题? 然而,你的应用是分层的Q可能每一个层都需要各自的框架。仅仅解决UI问题q不意味着你能够很好的业务逻辑和持久性逻辑和UI lg很好的耦合。例如,你不应该使具有JDBC代码的业务逻辑攑օ控制器之中,q不是控制器应该提供的功能。一个UI 控制器应该是轻量化的lgQ由它代表对UI范围之外的其它应用层的服务调用。良好的框架自然地Ş成代码分ȝ原则。更为重要的是,框架减轻?jin)开发h员从? 构徏持久层代码的_֊Q从而集中精力来应用逻辑上,q对客户端来说更为重要?/p>
本文讨论?jin)如何结合几个著名的框架来达到松散耦合Q如何设计你的架构,以及(qing)如何辑ֈ各个层次的一致性设计。面临的挑战是,框架整合v来,以每一
层都向另外的层次以一U松散的方式来暴露接口,而不底层功能用的是什么技术。本文还讨论整合3U著名开源框架的一U策略。对表现层,我们使用StrutsQ业务层使用SpringQ对于持久层我们使用的是Hibernate。你可以取代这里的某个框架而用你喜欢的框架已辑ֈ同样的效果。下图显CZ(jin)框架被整合v来时Q从最高层ơ看到的视图?br>
应用?/strong>
许多设计良好的web 应用Q可以被按职责分为四层。这些层ơ是表现层、持久层、业务层、和领域模型层。每一个层ơ都有其独特的职责,不能把各自的功能与其它层ơ相混合。每一? 应用层都应该和其它层隔离开来,但允怋用接口在层间q行通信。我们开始来看看每个层,q讨Z下它们各自都应该提供什么和不应该提供什么?/p>
表现?/strong>
一个典型的web 应用的末端是表现层。许多Java 开发者都知道Struts 提供?jin)什么东ѝ然而,太多时候,耦合代码比如业务逻辑被放qorg.apache.struts.Action中。所以,我们先ȝ一下Struts 之类的框架应该提供什么。下面就是Struts 的职责所在:(x)
下面是一些经常可以用Strutsq行~码但是不应该和表现层关联的事情Q?/p>
在表现层中引入这些类型的代码导致类型耦合和维护负担?/p>
持久?/strong>
一个典型Web应用的另一端是持久层。这也是应用中最Ҏ(gu)很快失控的地斏V开发者通常低估?jin)自己构q持久层框架的挑战。一个定制的Q内部开? 的持久层不仅需要大量的开发时_(d)q且通常~Z功能和难以管理。目前有许多解决q些问题的开源对象关pL?(ORM) 框架。特别地Q? Hibernate 框架允许Java中的对象-关系的持久性和查询服务。Hibernate 对已l熟(zhn)了(jin)SQL 和JDBC API 的Java开发者来或具有中度的学习(fn)曲线。Hibernate 的持久对象基于POJO和Java 集QcollectionsQ。此外,使用Hibernate 不和你的IDE接口。下面列Z(jin)你需要在持久性框架中~写的代码类型:(x)
下面是应该在持久层避免的一些事情:(x)
业务?/strong>
典型的Web应用的中间组件一般是业务层和服务层。从~程的角度来_(d)service layerl常被忽略。这U类型的代码散布于UI表现层和持久层ƈ不是不多见。这些都不是正确的地方因为它D?jin)紧密耦合的应用和难以l护的代码。幸q的 是,大多数框枉解决?jin)这个问题。这个空间内最行的两个框架是Spring 和PicoContainer。它们都被视为是h非常的QfootprintQƈ且决定如何将你的对象整合在一L(fng)微容? QmicrocontainerQ。这些框枉建立在一U叫做依赖性注入(dependency injectionQ? (也称控制反{Qinversion of controlQIOCQ?的简单概念之上。我们将xSpring中通过针对命名配置参数的bean属性的setter 注入的用。Spring 也允怸U更加高U的构造器注入Qconstructor injectionQŞ式作为setter injection 的可选替代。对象通过单的XML 文gq行q接Q该配置文g包含对各U对象的引用Q比如事务管理处理器Qtransaction management handlerQ?对象工厂Q包含业务逻辑的服务对象,以及(qing)数据讉K对象(DAO)?/p>
我们随后?x)用一些例子来澄清Spring中用这些改变的方式?/p>
业务层应该负责下面的问题Q?/p>
领域模型?/strong>
最后,因ؓ(f)我们要解军_际的问题的web应用Q我们需要一套在不同的层间移动的对象。领域模型层包含的是表达实际业务? 象的对象Q比如Order, OrderLineItem, Product {等。这一层允许能让开发者不再构建和l护不必要的数据传输对象DTO来匹配其领域对象。例如, Hibernate允许你读取数据库信息C个领域对象的对象图中Q以便你可以在离U的情况下将其表现在UI层中。这些对象可以被更新q跨q表现层发送回 去,然后q行数据库更新。另外,你不再需要将对象转变成DTOQ因为它们在不同的层间移动时可能?x)丢׃务。这U模型允许Java 开发者能够以OO风格的方式很自然的处理对象,而不用编写额外的代码?/p>
整合一个简单的例子
到此Q应该对各种层次和组件有一个高层的理解?jin)Ş。可以开始一些实践了(jin)。再ơ说明。我们的例子整合?jin)Struts, Spring, 和Hibernate 框架。每个框枉包含大量的内容细节,我们不会(x)多述。我们的目的使用一个例子向你说明如何将它们整合在一hZ个优雅的Web应用架构。实例将演示一? h是如何得到各层的服务的。此应用的用户可以将一个订单保存在数据库中q且察看数据中的已有订单。进一步的增强允许用h新和删除现有订单?/p>
首先Q我们将常见我们的领域对象,因ؓ(f)它们是要和各层沟通的。这些对象将允许我们能够定义那些对象需要持久化Q那些业务逻辑需要提供,以及(qing)应该设计
那些表现接口。接下来Q我们将使用Hibernate
来ؓ(f)领域对象配置持久层和定义对象关系映射。然后,我们定义和配置我们的业务层。在完成q些lg后,我们讨论如何用Spring这些层兌h?
最后,我们提供一个表现层Q它知道如何与业务服务层通信以及(qing)如何处理来自于其他层的例外?/p>