ASP.NET MVC4 Web 编程第五章

web应用程序架构

模型-视图-控制器模式是一种用户界面架构模式,促进跨多个应用层的分离关注点。mvc模式不提倡将所有数据访问代码的应用长须放在一个地方,提倡把应用程序逻辑封装到特定的类中,每个类都有自己特定的职责。

mvc模式并不是一个新概念,他既不依赖特定的.net框架,也不依赖web开发,事实上他最初十字20世纪70年代后期有xerox pace程序员创建的个应用于使用smalltalk语言的应用程序,从那以后,许多染认为mvc是有史以来最好的应用架构模式之一,这是应为mvc模式是一种非常高级别的模式,他已经形成了许多相关的实现框架和子模式。

分离关注点

分离关注点属于计算机科学原则,这条原则提倡将块多个组件的应用程序或盈利责任分开,每个组件都有自己的特定职责,介意用一组特定的功能或行为相关联,分离关注点传统上通过使用实现封装和抽象来更好的隔离其他组件的关注点,例如,分离关注点可以通过划分表示层,业务逻辑层和数据访问层,来设计应用程序架构,每个层在逻辑上和物理上都是分离的,

分离关注点是一条经常用于设计平台和框架的强大原则,例如在早期的web网页中,经常把布局,样式和数据放在同一文档中,许多年后,出现了基于分离关注点的标准,现在吧单个文档的样式,javascript文件,负责控制文档内容的行为,在mvc模式中,分离关注短用来定义关键组件的责任,模型,视图和控制器,图51展示了不同的mvc组件及其核心责

译注1 model-view-controller pattern简称为mvc 模式,1974年为smalltalk语言提出这种架构模式。

 

 

控制器: 拦截用户输入 协调视图和模型 处理模型个数据层之间的通信

模型:数据属性:业务逻辑,行为和验证

视图:渲染ui;绑定模型

至关重要的是,虽然每个单独的组件有器自己的责任,但是组件可以互相依赖,例如在mvc中控制器负责从模型中检索数据,并且把视图汇总的更该去同步会模型中,控制器可以与一个或多个视图像关联,每种视图一特定的方式负责显示数据,但它依赖控制器处理和检索数据,虽然组可能会严重依赖其他组件,但是每个组件之庄主与自己的责任,并且把其他的额责任留给别的组件处理。

最初设计mvc模式的时候,假设视图,控制器,和模型在同一上下文环境中,该模式严重依赖每个能够彼此直接交互,共享用状态的组件。例如,控制器将使用观察者模式监视要跟改的视图,并对用户输入做出反应,当控制器,视图都存在于相同的内存上下文环境中的这种方法非常有效

在web应用程序中,所有的东西都是无状态的,而且视图运行早起客户端的浏览器内,控制器不能使用观察者弄湿监视视图的变化,相反,一个HTTP请求需要从视图发送待空志气,如要解决此问题,可以使用抢断控制器模式这种模式的主要理念是当发送一个http请求时,控制器接货并处理它,控制器负责确定如何出炉改请求并将结构发送回客户端。

当现在的web应用程序腰围多个请求执行相同的逻辑代码是,虽然可能会为每个单独的请求返回不同的内容,但前端控制器模式的优势还是非常明显,例如,相同的控制器操作可以出里还只能唱的浏览器请求和ajax请求,但浏览器希望呈现单独是完整的网页(如布局,演示,脚本,文件等),而ajax请求期望的可能是部分html视图甚至是原始json数据,在所有哲学立足中控制器逻辑爆出不变,而且视图任然不知道数据时从哪儿来的。

 

 在asp.net mvc应用程序中路由和视图引擎涉及处理http请求的工作,当收到请求url时mvc运行库会在路由表中查找,并调用相应的控制器操作,控制器会处理该请求,并确定模型返回什么结果尅性,当返回视图结果时asp.net 框架会把架子和呈现相应请求视图的任务委派给视图引擎。

web应用架构设计

mvc架构的核心设计依据就是分离关注点原则,除了路由和视图引擎以外。mvc框架提倡使用操作过滤器,用于处理横切关注点,例如安全,缓存,和错误处理,当设计和构建一个mvc web应用程序时

横切光柱点是指相对于子上而下的请求流程,应用程序中有一些必须面对的问题,软圈,日志,缓存和错误处理等,这些问题就像在一个长条形上的物体,入在黄瓜上横向切了一道之后我萌看到的横切面,于是这些问题就被称为横切关注点”。

重要的是要了解这个mvc框架如何支持这条原则,已计入额和使用过这一原则来设计应用程序。

逻辑设计

应用程序的逻辑(概念)架构重点关注组件之间的关系和交互,以及这些组件如何在逻辑层中实现特定的功能。

组件的设计目标就是强化分离关注点以及使用抽象跨组件通信,横切关注点是将安全,日志和缓存等隔离到不同的应用程序服务中心,这些服务应该会吃即插即用的模块方法,切换不同的安全身份验证类型或使用不同的日志记录来源将不会影响应用程序的其他部分。

mvc web应用程序的逻辑设计

mvc框架的设计魔表就是提倡这种类型的逻辑设计,除了隔离司徒,控制器,和模型以外,mvc框架还包括处理不同类型横切的关注点的几个操作过滤器,以及为仕途 json,xml,部分页面定义多种操作结果类型,应为噶框架支持五香的扩展,所以开发人员可以创建并插上自己自定义操作沟路器和结果。

singlesignonattribute标记属性就是一个自定义的操作过滤器例子,他支持快多个web应用程序的单点登录神烦验证没代码如下:

 

 应用程序逻辑设计通行的最佳方法是为每个组件及其相应的层创建可视化表示形式,图5-3所示为典型的逻辑设计的asp,.net mvc web应用程序,注意横切关注点是如何分割成不同的应用程序服务的

表5-1介绍了图5-3所示中的不同元素。

 

 

 

 

 

 逻辑设计的最佳实践

图5-3所示的分层应用程序设计提供了最灵活的应用程序框架,每层拥有自己特定的职责,每层只是依赖堆栈上更低级别的层,例如,数据访问存储库与模型位于同一个层次,所以完全可以接受它只有一个依赖项,该模型与基础数据存储库是隔离的,它不在乎什么样的存储库如何处理持久化工作,也不关心是保存待本地文件还是数据库。

当设计web应用程序时,通常出现的争论就是,在哪里强制业务和验证规则,mvc模式提倡模型负责业务逻辑,这样虽然在分布式应用程序中,每层应该分别葱末中程度上的验证用户输入,但理想情况下应该失踪在发送到另一层之前警察输入数据。

每层应该承担它可以强化的验证级别责任,下游层永远不应嘉定调用层已验证了每个数据在客户端,应使用javascript来验证必填字段并限制常见ui控件的输入数据,应用程序业务模型应强制所有业务和验证规则,而且数据库层应该使用强类型字段和强约束以防止非法数据类型。

想要避免的几十在每个层之间赋值复杂的业务逻辑代码,如果显示界面针对普通用户和管理员尤其特定的功能,name业务模型应该可以确定哪些功能是启用还是禁用,并提供一个标志让不同用户用来吟唱或禁用挂你字段。

物理设计

物理架构设计的作用是为web应用车需定义物理组件和部署模型,大多数web应用程序都是局域N层模型的。客户端由HTML,CSS和web浏览器内部原型javascript组成,客户端向服务器发送http请求检索html内容,或者执行ajax请求已返回部分html页,xml或json数据,应用程序层包括mvc框架在(iis web服务器里运行)和任何兹定于或者应用程序使用的第三方程序集,数据层时可能包括一个或更多关系或NoSQL数据库,或一个或多个外部soap或者rest web服务,或者第三方应用程序编程接口(api)。

项目命名空间和程序集名称

在部署mvc web应用程序之前,开发人员需要决定如何将应用程序代码在物理上分隔成不同的命名空间和程序集,有很多不同的方法可用来设计asp.net mvc应用程序。开发人员可以在网站里保留所有的应用程序组件,或者把组件分离到不同的程序集中,在大多数情况下,把网站里保留的应用程序组件,活着吧组件分离待不同的程序集中,在大多数情况下,把网站的业务逻辑和数据访问层AOI不同的程序集是个不错的注意,这样做同尝试为了根号的隔离ui和业务模型,而且更易于编写自动化测试,把测试代码关注在核心应用程序逻辑上,另外,使用这种方法可以在其他应用里重用业务逻辑和数据访问层代码(如控制台应用程序,网站,web服务等)。

一个共同的根命名空间应该在所有程序集里都保持一致,每个程序集应该再次基础上创建自己的自命名空间,图5-4所示为网上购物网站ebuy引用的应用程序的项目结构,应用程序的功能已经被划分为三个项目,Ebuy。website包含视图,控制器和其他web相关的文件,ebuy。core宝行的业务模型的应用程序,custonextensions项目宝行的应用程序的模型绑定,路由和控制器以及使用的其他自定义扩张,此外该项目由两个测试项目

 

 部署选项

一旦定义了visual studio解决方案和项目结构,开发人员便可以自动或手动方式部署编译过的应用程序到web服务器,请参阅第19章有关如何部署mvc web应用程序的详细内容。

图5-5展示了已配置为使用多服务器web农场和sql server数据库集群mvc web应用程序 mvc web应用程序支持所有种类的部署模型,应用程序可以使用一个本地的sql server express数据库单独部署,也可以使用企业模型部署

物理设计的最佳实践

没有设计web应用程序架构的“万能银弹”,而且每种选择都各有利弊,但重要的是应用程序的设计应该是灵活的,并且包含适当的监控,这样可以根据实时监控数据来调整应用程序,这是mvc框架的最大亮点之一他在上机上就具备灵活性和可扩展性,以及插入不同的组建和服务能力。

 

 当设计一个web应用程序时,有很多需要考虑的因素,最重要的4个因素是性能,可扩张性贷款和延迟时间,处理一个或多个这些问题提所做的选择可以对其他因素产生影响,设置监视侧洛克以正确评估应用程序的工作状况,尤其是底层负载,而且可以确定适当的平衡因素。

性能和可伸缩性

处理性能或可伸缩性问题度会轻易影响到其他方面,如果一个应用程序的设计需要保留大量的缓存数据,name就会影响应用程序的内存使用,iis辅助进程要考虑内存使用要求以正确配置,如果内存分配太多内存,则工作进程将被回收,了解。net垃圾回收器如何释放资源也有非常重要的意义,不断的向会话状态里保存大型集合或数据对象可能导致对象带领正价。net垃圾回收器编辑该对象为第二代对象,或吧对象放入大对象堆中。

web农场是一种提高web应用程序可扩张性的好的方法,起关键理由是它是通过应用陈旭设计技术来实现的,使用web宁昌会影响用用程序处理的损失状态,如果硬件和软件支持符咋平衡,则可以使用保留会哈的方法确保用户总是将路由定位到它最初建立会话的服务器。

另一种提高可扩张性的方法是使用会话状态服务器或持久化会话状态导数据库,通常要尽量减少实用会话状态毛病却白哦以为缓存的数据定义超时规则。

由于会话状态和数据被换粗闹起来的位置是可配置的因此要确保你所有可能使用的类已正确设置为可序列化,这可以使用,net serialzableattribute标记属性,或者使用接口,f数据契约来支持序列化。

带宽和延迟时间

要处理带宽和延迟时间可能会有困难,延迟时间通常是恒定的约束,如果服务器位于纽约,而用户在日本浏览网站,则每个请求的延迟会非常严重,使用图片银蛇以及限制请求的数目,待框通常是变化的,但如果应用程序需要块网络发送大量的数据,成本可能就会非常高。

处理这些问题的最佳选择就是尽量减少请求的数量,并保持较小的有效载荷,好的策略是在可能的情况下,对大型结构集启用分页,网络上只发送必要的字段,利用客户端进行验证和缓存。

设计原则

当设计应用程序,框架或者类是最重要是考虑代码的可扩展性,而不仅仅是开发出某些基本功能,这种思想也应用到mvc框架设计中,整个框架都使用并且提倡使用面向对象设计的最佳实践和基本原则。

solidyuanze

是一些特定的面向对象应用程序开发原则的简称,它们用来指导面向兑现改的设计与开发工作,当整个应用陈谷采用这些原则是,这些技术将协同工作,可以创建出更易于测试和适应变化的模块化组件soild包括以下这些原则。

单一职责元则

是指对象应承担歹意的责任,它们的行为应该关注在责任上,一个很好的例子就是不同的现实界面对应不同的控制器,homecontroller应只包含主页有关的操作,而productcontroller应该只处理产品页面的操作,同样,视图应该只关注渲染ui,而且要避免任何数据访问逻辑。

如下所示的errorloggermanager类是打破了单一职责原则的一个常见类的例子,这种类有两个方法,一个将错误保存到时间日志中,一个用于将错误日志记录到文件,把这些方法组合到一起,在开始的时候并没有问题,但这个类包含了太多的职责,当添加其他日志记录方法时这个问题会变得更加明显,通常代码要提防的是名为xxxmanager的类,这种类可能包含了更多的职责。

 

开放封闭原则鼓励对扩展开放,对修改关闭,这一原则是对srp原则很好的补充,也就是说我盟应该通过继承类来扩展其功能,而不是向类添加更多的行为菏泽人,一个很好的例子就是横切光柱点服务,例如错误日志记录,他们都不是在相同的类中添加保存错误待数据库或文件的代码,而是创建一个抽象类,并由不同的子类实现自己的日志记录方法。

回顾一下errorloggermannage类就很容易看出这个类是如何潍坊这个类目前有两个非常特别的实现方法,logerroetoevetlog会把错误记录袋时间日志,而logerrortofiule会把错误记录袋文件中,若需要记录其他的错误日志类型那么这个类的可维护性就变得无法保证,变得无法控制。

这里是值遵守了srp和ocp的更新版errorlogger类,映入了一个名为ilogsource的接口。此外设立了两个子类继承子这个接口:eventlogsource和filelogsource,这两个类分别负责处理特定类型的日志记录,现在有醒的日志记录类型出现,而不需要修改任何享有的类了。

 

 

 

 此时我们可能会想,虽然这种方法看起来更清晰,但需要更多的实现代码,本书的例子将显示,遵守这些原则实现的松耦合的组件设计会带来许多好处。

里氏替换元原则的对象应易于被其子类型的实例替换,而不会影响对象的行为和规则,例如尽管有一个共同的基类或接口是个不错的注意,但是这种做法可能会引起代码间接打破lsp。

看看isecurityprovider和实现此接口的类,一切看起来都不错,直到usercontroller调用RemoveUserthractiveDirectoryProvider类,在此示例中,只有databaseprovider类支持删除用户,解决这一问题的一种方法是添加特定类型的逻辑代码,这正是usercontroller目前在做的,但这种方法有很大的确定:它打破了lsp。这种情况下会引发一个异常和强迫引入特定类型代码,是一个坏主意,要解决此问题的一种方法是利用solid的接口隔离原则,下面会进行详细讨论。

接口隔离原则鼓励在整个应用程序中使用接口的同时,限制接口的大小,换句话说,应存在多个更小,更多的特定接口,而不是一个包含所有对象行为的超类接口,一个很好的例子是,。net为序列化和销毁对象分别定义了单独的接口,一个类如果实现了ISerializable和IDisposable接口,那么就可以只关注序列化的调用者,只关心ISerializable接口的实现情况。

下面的代码是正确使用ISP的例子,创建两个单独的接口一个仅包含搜方法,另一个用来持久化实体对象,注意,搜索控制器只关注搜索行为,而且仅仅引用ISearchProvider接口,这是强大的应为可以使用这种技术来强制执行安全级别,例如假设允许任何人可搜索一种产品,但只有管理员可以添加删除产品,name通过使用isp可以确保允许匿名访问搜索控制器,且只搜索产品而并不会添加、移除它们。

 依赖倒置原则是指互相依赖的组件应该通过抽象来进行交互,而不是直接通过具体实现,使用这个原则的一个很好的例子,就是将依赖于一个抽象类或接口的控制器与数据访问层交互,而不是直接创建特定类型的数据访问对象进行通信

依赖倒置原则的优点是,使用抽象可允许不同的组件进行开发,彼此独立的进行更改,不仅可能引入新的抽象实现代码,而且易于测试,应为可以非常方便的魔力依赖项。

下一届将深入学习如何实现默写特定的依赖倒置原则,控制反转原则,这个原则可以让我们更容易通过单独组建来管理和创建这种抽象的生存期。

下面的代码是很好的依赖倒置原则的例子,searchcontroller类依赖于isearchprovider接口,而不是直接创建productrepository实例,控制器使用isearchprovider的实例传递到控制器中,下一届将介绍如何使用ioc容器来管理依赖。

 

 

ioc就是控制反转,意味着将设计好的类交给系统去控制,而不是在类内部控制。

控制反转

现在,我们已经整我了solid设计原则的概念,是时候吧这些原则放在一起使用了,控制反转是一种提倡实现松耦合层,组件和类的设计原则,它颠倒了应用程序的控制流程。

与传统的应用程序代码显示控制调用过程不同,ioc使用分离执行特定问题处理代码的概念,此方法允许独立开发应用程序的各个组件,例如,在mvc应用程序中,可以独立设计并构建模型,视图和控制器。

控制反转设计原则的两个最流行的实现就是依赖注入和服务定位,这两种方式使用相同的中心容器的概念来管理依赖项的生存期,两种实现方式的主要区别是如何访问依赖项,服务定位依赖调用者调用依赖,而依赖注入通过类的构造函数,属性或者执行方法来实现。

理解依赖

了解不同类型的依赖关系以及如何管理依赖项之间的关系是减少应用程序复杂性的关键所在,依赖关系有多种形式,.net程序集可以引用一个或多个其他。net程序集。mvc控制器必须继承mvc基类控制器。asp.net程序需要一个iis web服务器托管它。

图5-6所示为控制器和存储库之间的关系,这种方案时控制器直接创建存储苦累的一个实例,控制器与存储库紧密耦合,对存储库中的公共接口的任何更改可能会影响到控制器类,例如开发人员决定更改存储库类的默认构造函数,需要一个或多个参数,此更改会影响控制器类

 

 

为了使控制器与存储之间的关系更加松耦合,开发人员可以使用抽象类IREPOSITORY并把创建的存储类代码移动到工厂。控制器现在只是依赖Irepository接口,并对存储库类的构造函数的任何跟改都不阴险控制器类,虽然这消除了控制器和存储库之间的紧耦合,但是他映入可一种进纸器各工厂看了之间的新关系。

 

 

5-8显示了如何使用ioc容器替换工厂类,作为一种手段来管理控制器和存储苦衷类之间依赖关系,此事项代码仍然使用irepository接口作为控制器的抽象,现在只有及控制器不知道存储库是怎么创建的,ioc容器负责创建并注入到口昂志器的存储库尅是里,使用ioc荣区为工厂提供其他级别的功能,可以通过配置ioc容器来是想类的声明周期管理。

使用服务定位器方式非常简单,开发人员只需要通过ioc容器获取一个特定的服务类即可,用容器来检查被请求的类是否已配置,并且根据配置的生命周期管理规则创建一个新实例,或返回给请求这一个以前创建的实例。

服务定位器方式的功能十分强大,如要直接访问数据库中的某项特定服务,单个方法,仅需要请求服务的名称,并不需要接口,使用这种模式的主要确定是代码需要直接访问ioc绒球,这会导致代码和Ioc容器api之间的紧密耦合,一种降低耦合的方法就是通过接口使用更抽象ioc容器。

下面就是根据注册接口,调用IOC容器获取特定服务的示例代码:

 

 依赖注入

与服务定位方式相比,依赖注入方式提倡采用更松散耦合的方法,di通过构造函数,属性或方法传递依赖,通常情况下,大所述开发人员使用构造函数注入,应为大多数情况下需要立即使用依赖,然而默写ioc容器允许通过延迟加载方法注入依赖这种情况下调用属性之前是不会加载依赖项的,

auctioncontroller类已经设置了够着函数注入方式,这个控制器类适用数据存储库来持计划和禅心相关的交易数据ranger该控制器并没有直接引用存储库的实现代码,相仿没空主使用试试接口,而且ioc容器会确定正确dipresiposy是想类并且在陨石注入他:

 

 

依赖注入真正开始显示为威力的时候是在设计多个级别的依赖关系的时候,例如自己的依赖有其他依赖项的情况,当ioc容器注入一个依赖项时,他将检查是否已经有一个以前加载依赖项的实例,如果没有,他就会创建一个新实例,以查看它是否需要注入其他依赖项,在此方案中,当ioc容器遍历依赖树时,它就会创建必要的依赖。

下面的例子展示了依赖连的工作原理,当ioc容器创建auctionscontroller实例是,他首相就会探测这个类是否依赖irepository接口,然后会检查是否注册了Irepository的实例,并创建auctionsrepository对象,应为这个里包含了自己的依赖,故ioc容器将创建一个erroelogger的实例并注入调auctionrepository中:

 

 

 

 当使用控制反转时,开发人员要记住两件事情,性能和错误处理蛮实用ioc容器来管理并注入依赖的代价可能非常大,依赖需要合适的生命周期,如果某个依赖配置为单例模式,就可能会硬气跨线程访问的问题,而且需要安全管理外部资源,不要使用ioc容器创建大的集合对象,比如使用地来创建的班行1000个项目的集合杜爱香,要尽量避免这种做饭错误使用或者放机注册依赖,对调试来说是个噩梦,开发人员续爱要更新总想用的依赖项,而且要确保在应用程序启动的时候正确浇在所有的依赖项。

应为绝大部分ioc容器都十分相似,所以选择哪个ioc容器并不一点要经过消息的比较,很多时候都是开发人员拼自己的喜好来选择,有几个可以使用ioc容器,每个都提供了不同的注入荷光路依赖的方法,最流行的ioc容器如下

 

 

对电子交易网站Ebuy来说,使用的是Ninject容器,应为这个ninject容器在mvc开发社区非常流行,它包含许可以自asp.net平台上使用的自定以扩展功能,非常易于配置he注册依赖。

要初始化和使用Ni ioc容器,就需要设置启动项目,启动程序项目,启动夏目负责管理使用Ninject注册的模块

要检查的最终要的模块几十bingmodule注意bootstrpper类的strart()方法和stop()犯法,这些方法需要在global,asax应用程序启动的时候调用,下面展示的是如何使用ninject bootstarpper类;

 

 

 

 使用控制反转扩展mvc

mvc框架严重依赖控制反转原则,这一框架包含了现成的控制器工厂类,可以通过拦截输入的请求,读取mvc路由信息来创建特定的控制器,左后根据路由定义来调用控制器的方法,ioc的里一个主要应用领域是管理应用程序的视图引擎,以及控制=控制器和其相应的视图之间的执行过程。

只有在我呢个通过使用子弟你ioc容器重写默认为以来解析器扩张框架来获取直接控制asomvc管理依赖和创建对象的权力时候才能真正体现ioc的强大,重写mvc默认的依赖解析器和实现idependencyresolver接口一样简单,而且可以使用mvc框架祖册自定义依赖解析器。

若要深入了解这个问题,就可以看一下如何使用ninjectioc来创建一个自定意义来解析器,首相是想idepengdecyResolver接口,然后通过调用够着函数来床底ikerner的子类实例代码如下

 

 其次,通过调用雷伤的静态方法setresolver来实现注册,代码如下,

 

 注意我盟是如何必须开始创建一个实例,然后传递给虽让每个ioc容器的事项凡事不同但大所述ioc框架在创建和解析依赖广西之前否要求配置容器,在这个例子中提供相同的默认配置。

上面的代码还不鞥正常执行,必须想告诉standardkernael,需要它来管理类和接口,使用框架,可以使用bind方法来是想,例如当需要使用ierrieloghher时就可以告诉调用具体实现了ierrorlogger

 

 dry原则是一项与solid原则密切相关的设计原则,他鼓励开发人员避免重复相同或者非常相似的代码。卡一下可以看到任何亲在weifangday原则的代码吗,看起来一非常正确,知道我盟看出应用陈旭中大概有几十个控制器所宝行的带那几护士完全相同板房沟会中广核彼此类似,最初,可能认为吧方法一道孔子器积累里是个不错的注意sure安总金额欧诺个放弃那个发keyUI张,但框架童了一种更好的板房开发人员可以创建自定义操作过滤器来处理这种行为。

 

 

本章介绍了mvc框架设计过程找那个使用关键设计模式和原则,开发人员可以使用这些原则构建灵活,可维护的asp.net mvc web应用程序,使用这些原则远远超出了写好代码的要求,他们是web应用程序架构设计中必须掌握的只是技能。

posted @ 2020-09-03 16:51  ZELDA小菜鸟  阅读(180)  评论(0编辑  收藏  举报