当前位置: 首页 > 科技观察

分享一个MVC的多层架构,欢迎大家一起看看

时间:2023-03-13 12:19:15 科技观察

多层架构是什么?多层架构是开发人员在开发过程中面对复杂多变的需求而采用的一种基于隔离控制的策略。关于多层架构的标准,我觉得有一句话比较有代表性“每一层都可以单独部署”,最传统最简单的就是从三层开始:从下到上划分整个项目:数据持久化(数据访问)层、逻辑(业务)层、UI(表现)层。数据访问层:负责将数据持久化到数据存储设备上,如DataBase、Txt、Excel等。业务逻辑层:负责处理为满足软件需求而定制的一系列逻辑和业务。例如,用户在前端下单后,整个业务流程可能涉及,获取用户信息,获取商品信息,获取购物车信息,验证可购买的商品数量是否满足本次购买会产生用户身份不同的优惠政策。同时会校验Cookie、Session等产生的数据的有效性,最终会产生一个订单。订单生成后,会涉及到仓储和物流。一系列的Erp系统业务,都属于“下单”需求的业务逻辑。表示层:负责与用户交互的界面。好的用户体验多用在这里。如果你学过Petshop,那三层就很熟悉了:但是随着业务的复杂化,每一层都会有自己的演进,最后三层依附的框架和开发思路不计其数。Mvc和MVP:首先,我一直认为这两个东西属于表现层,“表现层MCV”和“表现层MVP”。那么我们从表现层的角度来思考“Mvc”和“MVP”。Mvc:分为模型、控制器、视图。相信大家都已经很熟悉了,这里就不再赘述了。MVP:MVP有三个层次:Model-Presenter-View。其实楼主刚接触Mvc的时候就想过直接通过Controller和Model交互会不会“不干净”,因为在楼主眼里这个“表现层Controller”,应该是什么做的最多的是请求路由的不同响应和调用,但是在很多例子中,一些数据校验和去坏操作过程都放在了Controller中,显得不伦不类。当MVP出现的时候,一切都符合宿主的幻想。P的进程满足了这个要求。P扮演中介的角色,负责接收视图请求,然后将结果映射到视图。P不需要强引用View,可以通过IView适配多个视图。当然,我这里也会对终端数据做一些校验和过滤。业务逻辑:从描述中可以清楚地看出,整个自上而下的结构中最复杂、最容易失去控制的是业务逻辑层,因为它包含了很多不可控因素,每个行业领域的需求都有不同要求。可能包含自己的领域知识。因此,在后续多层架构的发展中,更多的变化和智慧都体现在这里。Domain-driven:限于我自己的天赋,这里不能分享太多,以免误导大家。想了解更多可以参考园内其他大牛。其实没有3、5年的相关经验是很难理解的。个人认为,如果你不理解,也不会影响你,因为领域驱动是基于良好的面向对象分析和边界划分,可以帮助你在学习过程中学到足够的知识。没登到山顶也没关系。简单来说,这个思路最重要的就是脱离了以业务领域为核心,希望其他部分的变更方案不影响领域模型,也就是为了“业务”复杂系统应用中的规则行为(即“领域逻辑”)会经常变化,我们必须拥抱这种变化。”结构图:CQRS:指命令和查询职责分离。它是一种小图案形式。这个模式的关键是:“一个方法要么用来改变一个对象的状态,要么用来返回一个结果,这两者不会同时共存。”将整个系统分成两部分:命令(command)——改变一个对象或整个系统的状态(有时称为修饰符或增变器)。查询-返回一个值并且不改变对象的状态。架构图:不管是DDD还是CQRS,其实这两种都不是100%适合所有的项目架构。这就需要架构师根据项目本身的特点和需求来选择,但是我们可以在项目的任何地方使用其中的思想。基于消息的分发:其实不管用什么样的架构,加入什么样的架构思想(soa),核心或者开发者最想达到的就是层次,系统之间解耦,没有人喜欢复杂事物。随着系统的发展,我们的程序会涉及到多台服务器和各种终端。同时,我们引入了基于消息的分布式架构来进行解耦。首先,系统的通信是基于消息的,逻辑上的联系不会涉及到具体的业务实现。同时,消息的传递成本更低,可以适应各种终端。其次,由于所使用的逻辑只是基于消息来实现,因此迭代的成本会比其他耦合项目更快更方便。展示层:随着Web2.0的到来,单个页面展示的信息也更加丰富。Ajax和js的流行也使得Ui端的操作越来越繁重,所以大家期待用工程化的思想来拥抱这种变化,于是MVVM,js的Mvc框架相继出现。同时随着移动互联网的兴起,不同的终端对于系统连接也很重要,所以我们考虑在Ui和Logic之间引入一个Application或者Service层来处理不同的终端配置。比如:我们在ClientPresenterLayer中加入了WCF来适配各种终端提交的订单,都是基于消息的。楼主使用的电商系统是针对淘宝、天猫、亚马逊的订单。出现库内订单并发,导致“超买”的情况,通过在上层Ui和逻辑层之间引入OrderChannel层,解决不同终端排队订单的问题。以上就是建立一个可以适应不同需求的架构的过程,但是真正的道理需要在实践中从错误中学习。下面是楼主简单的小分层结构。这是不合适的。希望大家多多指导,改正不足。#p#分层划分:为了实现分离部署,层之间进行了解耦,所以层都是基于接口来实现的。DataAccess层引入存储实现统一DTO操作,基于Ef:IRepository:publicinterfaceIRepositorywhereT:class{IEnumerableFindAll(Expression>exp);无效添加(实体);voidDelete(Tentity);无效提交();}导入RepositoryBase实现接口定义:publicclassRepositoryBase:IRepositorywhereT:class{DbContextcontext;publicRepositoryBase(DbContext_context){context=_context;}publicRepositoryBase(){this.context=newTestDBEntities();}publicIEnumerableFindAll(Expression>exp){returncontext.Set().Where(exp);}publicvoidAdd(Tentity){context.Set().Add(entity);}publicvoidDelete(Tentity){context.Set().Remove(entity);}publicvoidSubmit(){context.SaveChanges();}}对于单个存储,我们单独引入它自己的存储接口:publicinterfaceIUserRepository:IRepository{IListGetAllById(intid);boolCheckUserExist(UserTestu);}具体的repository实现:publicclassUserRepository:RepositoryBase,IUserRepository{publicIListGetAllById(intid){using(TestDBEntitiesentities=newTestDBEntities()){varusers=fromuinentities.UserTestswhereu.ID==idselectu;returnusers.ToList();}}publicboolCheckUserExist(UserTestu){using(TestDBEntitiesentities=newTestDBEntities()){Listusers=entities.UserTests.Where(ut=>ut.UserName==u.UserName&&ut.UserPassword==u.UserPassword).ToList<用户测试>();returnusers.Count==0?false:true;}}}在服务层同类型建立相关接口适合配种服务:IUserCore:publicinterfaceIUserCore{CommandStatueEnumUserLogin(IModelmodel);CommandStatueEnumUserRegister(IModelmodel);ListGetUsers(表达式>expr);}UserCore:publicclassUserCore:IUserCore{#regionStructureIUserRepository_repository;publicUserCore(IUserRepositoryrepository){this._repository=repository;}#endregionpublicCommandStatueEnumUserLogin(IModelmodel){try{UserLoginu=modelasUser登录;UserTestuTest=newUserTest();uTest.UserName=u.UserName;uTest.UserPassword=u.密码;如果(_repository.CheckUserExist(uTest)){returnCommandStatueEnum.Succeed;}else{returnCommandStatueEnum.Fail;}}catch(Exceptionex){throwex;}}publicCommandStatueEnumUserRegister(IModelmodel){try{UserLoginu=modelasUserLogin;UserTestuTest=newUserTest(){UserName=u.UserName,UserPassword=u.Password};_repository.Add(uTest);_repository.Submit();returnCommandStatueEnum.Succeed;}catch(Exceptionex){throwex;}}publicListGetUsers(System.Linq.Expressions.Expression>expr=null){return_repository.FindAll(expr).ToList();}}控制器:publicclassAccountController:Controller{IUserCoreuserCore;publicAccountController(IUserCore_userCore){this.userCore=_userCore;}////GET:/Account/#regionviewpublicActionResultHome(){ViewBag.Users=userCore.GetUsers(u=>u.IsUse==1);返回视图();}publicActionResultLogin(){returnView();}publicActionResultRegister(){returnView();}#endregion#regionPost[HttpPost]publicActionResultLogin(UserLoginaccount){try{if(userCore.UserLogin(account)==CommandStatueEnum.Succeed){returnRedirectToAction("Home");}else{returnView();}}catch(Exceptionex){ExceptionModel.IsExcept=true;ExceptionModel.Exception=ex.ToString();ExceptionModel.CreateTime=DateTime.Now;返回视图();}}[HttpPost]publicActionResultRegister(UserLoginaccount){try{if(userCore.UserRegister(account)==CommandStatueEnum.Succeed){returnRedirectToAction("Home");}else{returnView();}}catch(Exceptionex){ExceptionModel.IsExcept=true;ExceptionModel.Exception=ex.ToString();ExceptionModel.CreateTime=DateTime.Now;返回视图();}}#endregion}对于接口之间我们通过引入IOC工具解析:publicclassMvcApplication:System.Web.HttpApplication{protectedvoidApplication_Start(){AreaRegistration.RegisterAllAreas();我们bApiConfig.Register(GlobalConfiguration.Configuration);FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);RouteConfig.RegisterRoutes(RouteTable.Routes);BundleConfig.RegisterBundles(BundleTable.Bundles);AuthConfig.RegisterAuth();SetupResolveRules(建造者);builder.RegisterControllers(Assembly.GetExecutingAssembly());varcontainer=builder.Build();DependencyResolver.SetResolver(newAutofacDependencyResolver(容器));#endregion}privatevoidSetupResolveRules(ContainerBuilderbuilder){//组件使用ContainerBuilder构建器的As()方法连接到服务。RegisterType().As();builder.RegisterType().As();}}我们会根据具体需求定制其他基础类库。上面的例子中经常有不合适的部分,仅供演示之用。综上所述,本文仅以启发他人为目的。还请大牛指导。原文链接:http://www.cnblogs.com/xiguain/p/3636022.html【小编推荐】从Script到CodeBlocks,CodeBehind到MVC、MVP、MVVM5分钟快速开发代码生成器asp.netmvc4用VisualStudio2013开启MVC5之旅20个JavaScriptMVC开源框架SpringMVC+JQuery+GoogleMap打造IP位置搜索应用