英语原文共 16 页,剩余内容已隐藏,支付完成后下载完整资料
Pro Spring MVC: With Web Flow
马特·戴尼姆 与 科林·耶茨、赛斯·拉德和克里斯托夫·范弗伦
Web应用程序体系结构
在我们开始进入Spring MVC内部的旅程之前,我们首先需要了解web应用程序的不同层。我们将首先简要介绍MVC模式,包括它是什么以及为什么要使用它。我们还将介绍Spring框架提供的一些接口和类,以表示MVC模式的不同部分。
在回顾MVC模式之后,我们将浏览web应用程序中的不同层,并了解每个层在应用程序中扮演什么角色。我们还将探讨Spring框架如何帮助我们在不同的层中工作,以及如何利用它来发挥我们的优势。
MVC模式
模型-视图-控制器模式(MVC模式)是trygfeenskag在施乐公司从事Smalltalk时首先描述的。当时,这种模式是针对桌面应用程序的。此模式将表示层划分为不同类型的组件。每个组件都有自己的职责。视图使用模型来渲染自身。基于用户操作,视图触发控制器,控制器反过来更新模型。然后,模型通知视图(重新)呈现自身(参见图3-1)
图3-1。MVC模式
MVC模式就是关注点的分离。如前所述,每个组件都有自己的角色(见表3-1)。关注点的分离在表示层中很重要,因为它帮助我们保持不同组件的干净。这样,我们就不会在实际的业务中负担逻辑、导航逻辑和模型数据。遵循这种方法可以很好地分离所有内容,这使得维护和测试我们的应用程序更加容易。
表3-1。简称MVC
组成 |
描述 |
模型 |
模型是视图所需的数据,以便可以对其进行渲染。它可能是用户下的订单或要求的书籍列表。 |
视图 |
视图是实际的实现,它使用模型在web应用程序中呈现自己。这可以是JSP或JSF页面,但也可以是页面的PDF或XML表示。 |
控制器 |
控制器是负责响应用户采取的操作(如表单提交或单击链接)的组件。控制器更新模型并采取其他所需的操作,例如调用服务方法来下订单。 |
MVC模式的经典实现(如图3-1所示)涉及到用户触发一个操作。这将提示控制器更新模型,从而将更改推回到视图中。然后,视图使用模型中更新的数据更新自身。这是MVC模式的理想实现,例如,它在基于Swing的桌面应用程序中工作得非常好。然而,由于HTTP协议的性质,这种方法在web环境中是不可行的。对于web应用程序,用户通常通过发出请求来启动操作。这将提示应用程序更新和呈现视图,并将其发送回用户。这意味着我们在web环境中需要一种稍微不同的方法。我们需要从服务器中提取更改,而不是将更改推送到视图中。
这种方法看起来相当可行,但在web应用程序中应用并不像人们想象的那么简单。Web(或HTTP)在设计上是无状态的,因此保持一个模型是非常困难的。对于Web,MVC模式被实现为Model 2架构(参见图3-2)1。原始模式(模型1如图3-1所示)和修改后的模式之间的区别在于,它包含一个前端控制器,该控制器将传入的请求分派给其他控制器。这些控制器处理传入的请求,返回模型并选择视图。
图3-2。Model2 MVC模式
前端控制器是处理传入请求的组件。首先,它将请求委托给合适的控制器。当该控制器完成处理和更新模型时,前控制器将根据结果确定要渲染的视图。在大多数情况下,这个前控制器被实现为javax.servlet.servletservlet(例如struts中的ActionServlet或JSF中的FacesServlet)。在SpringMVC中,这个前控制器是org.springframework.web网站.servlet.DispatcherServlet.
应用程序的分层
在引言中,我们提到一个应用程序由几个层组成(见图4-3)。我们喜欢将层视为应用程序关注的领域。因此,我们也使用分层来实现关注点的分离。例如,视图不应该被业务或数据访问逻辑所负担,因为这些都是不同的关注点,通常位于不同的层中。
应该将层视为概念边界,但它们不必彼此物理隔离(在另一个虚拟机中)。对于web应用程序,层通常运行在同一个虚拟机中。Rod Johnson的书《专家一对一J2EE设计与开发》(Wrox,2002)对应用程序的分布和扩展进行了很好的讨论。
图3-3。典型应用层
图3-3是SpringMVC应用程序层的高度通用视图。这种分层可以在许多应用程序中看到。数据访问位于应用程序的底部,呈现在顶部,服务(实际业务逻辑)处于中间。在这一章中,我们将看一看这个体系结构,以及一切是如何组织的。表3-2提供了不同层的简要说明。
表3-2。图层概述
层 |
描述 |
演示 |
这很可能是一个基于web的解决方案。表示层应尽可能薄。还应该可以提供其他表示层,如web前端,甚至可能是web服务外观。所有这些都应该在设计良好的服务层上运行。 |
服务 |
包含业务逻辑的实际系统的入口点。它提供了一个粗粒度接口,允许使用系统。这也是应该作为系统事务边界的层(可能还有安全性)。这个层不应该知道(或者尽可能少地)关于持久性或者所使用的视图技术的任何信息。 |
数据存取 |
一种基于接口的层,提供对底层数据访问技术的访问,但不向上层公开。这一层抽象了实际的持久性框架(如JDBC、JDO或JPA)。注意,这个层不应该包含业务逻辑。 |
各层之间的通信是自上而下的。服务层可以访问数据访问层,但数据访问层不能访问服务层。如果您看到这些类型的循环依赖项逐渐进入应用程序,请后退几步,重新考虑您的设计。循环依赖项(或从下到上的依赖项)几乎总是设计不好的一个标志,并导致复杂性增加和应用程序维护困难。
注意,有时,人们也可能会遇到术语tier。许多人可以互换地使用层和层;但是,在讨论应用程序体系结构或其部署时,将两者分开会有帮助。我们喜欢使用层来表示应用程序中的概念层,而层则表示部署时不同机器上的层的物理分离。分层思考有助于软件开发人员,而分层思考有助于系统管理员。
尽管图3-3给出了web应用程序的层的一般概述,但我们可以进一步分解它。在典型的web应用程序中,我们可以识别五个概念层(见图3-4)。我们可以将表示层分为web和用户界面层,但应用程序也包括域层(请参阅本章后面的“Spring MVC应用程序层”一节)。通常,域层跨越所有层,因为它在从数据访问层到用户界面的任何地方都使用。
图3-4。Web MVC应用层
请注意,分层体系结构并不是唯一的应用程序体系结构;但是,它是web应用程序最常遇到的体系结构。
如果我们看看示例应用程序,图3-4所示的体系结构在包结构中是显式的。这些包可以在书店共享项目中找到(参见图3-5)。主要软件包包括:
com.apress.prospringmvc.bookstore.domain: the domain layer
com.apress.prospringmvc.bookstore.service: the service layer
com.apress.prospringmvc.bookstore.repository: the data access layer
其他包是web层和com.apress.prospringmvc公司.书店.config包包含根应用程序上下文的配置类。用户界面和web层我们在本书的过程中,这些层将在com.apress.prospringmvc公司.书店.web在用户界面所需的Java服务器页面中打包和
图3-5。书店包概述
关注点分离
正如我们在第2章中提到的,必须明确区分关切。如果我们从图3-4看架构,关注点的分离就出现在层中。将关注点分为不同的层有助于我们实现一个干净的设计,以及一个灵活和可测试的应用程序。
创建或检测层可能很困难。一个经验法则是,如果一个层与其他层有太多的依赖关系,我们可能希望引入另一个包含所有依赖关系的层。另一方面,如果我们在不同的层中看到一个单独的层,我们可能需要重新考虑这个层,并使它成为应用程序的一个方面。在这种情况下,我们可以使用Spring框架中的AOP功能在运行时应用这些方面(参见第2章)。
耦合层例如,服务层需要通过定义清晰的接口与数据访问层进行对话。定义接口和接口编程减少了与具体实现的实际耦合。这减少了耦合,降低了复杂性,从而使应用程序更易于测试和维护。使用接口的另一个好处是Spring可以使用JDK动态代理2来创建代理并应用AOP。
注意Spring也可以在基于类的代理上应用AOP;但是,这需要cglib库
关键是:应用程序中的分层将导致更易于维护和测试的应用程序。关注点的清晰分离也会导致良好的应用程序体系结构。
Spring MVC应用层
您可能会想知道所有层如何适应Spring MVC应用程序,以及所有不同的层如何帮助我们构建springmvc应用程序。在本节中,我们将查看图3-4中描述的五个层。我们将特别注意不同层次所扮演的角色,以及每个层次应该扮演的角色。
域层
域是应用程序中最重要的层。它是我们正在解决的业务问题的代码表示,它包含我们域的业务规则。这些规则可以检查我们是否有足够的资金从我们的帐户转账,或者确保字段是唯一的(例如,系统中的用户名)。
确定域模型的一种流行技术是将用例描述中的名词用作域对象(例如,帐户或事务)。这些对象包含状态(例如,帐户的用户名)和行为(例如,帐户的信用方法)。这些方法通常比服务层中的方法更细粒度。例如,在第2章中的货币转移示例中com.apress.prospringmvc公司.汇款.domain.Account对象具有借方和贷方方法。信用方法包含一些业务逻辑,用于检查我们的帐户中是否有足够的钱来转账。
在第2章中com.apress.prospringmvc公司.转帐服务转帐服务使用这些支持方法来实现用例(在示例中,它将钱从一个帐户转移到另一个帐户)。这不应该与贫血领域模型3混淆,在该模型中,我们的领域对象只保持状态,没有行为。
通常,您的域模型不需要注入依赖项;但是,仍然可以这样做。例如,可以使用Spring框架和AspectJ在我们的域对象中启用依赖注入。在这种情况下,我们会给我们的域类org.springframework.beans网站.factory.annotation.Configurable工厂注释可配置注解。接下来,我们将需要设置加载时编织或编译时编织,并且我们将注入依赖项。有关此主题的更多详细信息,请参见弹簧参考指南4。
注意这是SpringRoo5中使用的设置。它使用了一个由Eric Evans6倡导的富域模型。
用户界面层
用户界面层将应用程序呈现给用户。此层将服务器生成的响应呈现为用户客户端请求的类型。例如,web浏览器可能会请求HTML文档,web服务可能需要XML文档,而另一个客户机可能会请求PDF或Excel文档。
我们将表示层分为用户界面和web层,因为尽管有各种不同的视图技术,我们还是希望尽可能多地重用代码。我们的目标是只重新实现用户界面。有很多不同的视图技术,包括JSP(X)、JSF、Velocity和Freemarker等等。在理想的情况下,我们可以在不改变应用程序后端的情况下切换用户界面。
Spring MVC帮助我们将用户界面与系统的其他部分隔离开来。在Spring中,视图由一个接口表示:org.springframework.web网站.servlet.View. 此接口负责将操作结果从用户(模型)转换为用户请求的响应类型。视图接口是通用的,它不依赖于特定的视图技术。对于每个受支持的视图技术,都有一个由Spring框架本身或视图技术本身提供的实现。开箱即用,Spring支持以下视图技术:
用户界面通常依赖于域层。有时,直接公开和呈现域模型是很方便的。当我们开始在应用程序中使用表单时,这尤其有用。例如,这将允许我们直接处理域对象,而不是附加的间接层。有人认为这会在层之间产生不必要或不需要的耦合。但是,创建另一个层的唯一目的是将域与视图分离,这会导致不必要的复杂性和重复。无论如何,重要的是要记住Spring MVC并不要求我们直接向视图公开域模型,是否这样做完全取决于我们自己。
网络层
web层有两个职责。第一个职责是引导用户浏览web应用程序。第二层是服务层和HTTP之间的集成层。
在网站中导航用户可以简单到将URL映射到视图或像Spring Web flow这样全面的页面流解决方案。导航通常只绑定到web层,域或服务层中没有任何导航逻辑。
作为一个集成层,web层应该尽可能的薄。它应该是将传入的HTTP请求转换为服务层可以处理的内容,然后将服务器的结果(如果有的话)转换为用户界面的响应的层。web层不应该包含任何业务逻辑,这是服务层的唯一目的。
web层还包括cookies、HTTP头文件和HTTP会话。web层的责任是一致和透明地管理所有这些事
剩余内容已隐藏,支付完成后下载完整资料
资料编号:[410014],资料为PDF文档或Word文档,PDF文档可免费转换为Word
以上是毕业论文外文翻译,课题毕业论文、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。