溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

MVC的多層架構(gòu)怎么實現(xiàn)

發(fā)布時間:2022-01-12 10:35:25 來源:億速云 閱讀:116 作者:iii 欄目:編程語言

本文小編為大家詳細(xì)介紹“MVC的多層架構(gòu)怎么實現(xiàn)”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“MVC的多層架構(gòu)怎么實現(xiàn)”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。

多層架構(gòu)是什么?

多層架構(gòu)是開發(fā)人員在開發(fā)過程當(dāng)中面對復(fù)雜且易變的需求采取的一種以隔離控制為主的應(yīng)對策略,關(guān)于多層架構(gòu)的標(biāo)準(zhǔn),我認(rèn)為有一句話是比較有代表性的“每一層都可以單獨部署”,最傳統(tǒng),最簡單的就是從三層開始的:

MVC的多層架構(gòu)怎么實現(xiàn)

將整個項目自下而上的分為:數(shù)據(jù)持久(數(shù)據(jù)訪問)層,邏輯(業(yè)務(wù))層,UI(展現(xiàn))層。

數(shù)據(jù)訪問層:負(fù)責(zé)將數(shù)據(jù)持久化響應(yīng)的數(shù)據(jù)存儲設(shè)備上,如DataBase,Txt,Excel等。

業(yè)務(wù)邏輯層:負(fù)責(zé)處理為滿足軟件需求而訂制的一系列的邏輯與業(yè)務(wù),如用戶在前端下訂單之后,整個業(yè)務(wù)流可能涉及到,獲取用戶信息,獲取商品信息,獲取購物車信息,驗證商品可購買數(shù)量是否滿足本次購買,針對用戶身份產(chǎn)生不同的優(yōu)惠策略,同時會驗證Cookie,Session等端產(chǎn)生數(shù)據(jù)的有效性,最終才會產(chǎn)生訂單,而訂單產(chǎn)生之后會涉及到倉儲物流等一系列的Erp系統(tǒng)業(yè)務(wù),所有的這一套都屬于“下訂單”這一需求的業(yè)務(wù)邏輯。

展示層:負(fù)責(zé)與用戶交互的界面,良好的用戶體驗多是使用在這里。

學(xué)習(xí)過Petshop的話,對于三層都不會陌生:

MVC的多層架構(gòu)怎么實現(xiàn)

但是隨著業(yè)務(wù)的復(fù)雜每一層都會有自己的進(jìn)化,最終有了無數(shù)附加在三層之上的框架與開發(fā)思想。

Mvc與MVP:

首先我一直認(rèn)為這兩種事屬于展現(xiàn)層的,“展現(xiàn)層MCV”,“展現(xiàn)層MVP”。

然后我們站在展現(xiàn)層的角度思考一下“Mvc”與“MVP”。

Mvc:分為model,Controller,View,相信大家對于他已經(jīng)很熟悉了,在此不再累述。

MVC的多層架構(gòu)怎么實現(xiàn)

MVP:MVP有Model-Presenter-View三個層次

MVC的多層架構(gòu)怎么實現(xiàn)

其實在樓主最開始接觸Mvc的時候,就在想如果直接通過Controller與Model交互是不是顯得有一些“不干凈”,因為在樓主眼里“展現(xiàn)層的Controller”,做得最多的應(yīng)該就是對于請求路由的不同響應(yīng)與調(diào)用,但是很多的例子會將一些數(shù)據(jù)驗證,去糟的操作過程放在Controller中,顯得不倫不類。當(dāng)MVP出現(xiàn)的時候,一切滿足了樓主的幻想,P的過程就是滿足了這一需求,P起到中介的作用,負(fù)責(zé)接收視圖請求,再把結(jié)果映射到view上,P可以不對View做強引用,可通過IView適配多個view。當(dāng)然我也會在這里做一些針對于終端數(shù)據(jù)的驗證與過濾。

業(yè)務(wù)邏輯:

從描述上可以看的很清楚,整個自上而下的結(jié)構(gòu),最復(fù)雜,最可能失控的就是業(yè)務(wù)邏輯層,因為其中包含著許多的不可控因素,每個行業(yè)領(lǐng)域的需求都有可能包含自身的領(lǐng)域知識。于是在之后的多層架構(gòu)發(fā)展構(gòu)成當(dāng)中,更多的變化與智慧是體現(xiàn)在這里。

領(lǐng)域驅(qū)動:限于本人才學(xué)不能在這里分享太多,以防誤導(dǎo)大家,想了解更多可參考園子里的其他大牛,其實沒有3,5年相關(guān)經(jīng)驗是很難理解的,個人感覺如果你不理解的話也不會對你有什么影響,因為領(lǐng)域驅(qū)動是建立在良好的面相對象分析,邊界劃分基礎(chǔ)之上的,在學(xué)習(xí)的過程當(dāng)中已經(jīng)能幫助你去學(xué)習(xí)到足夠多的知識了,最終到不到山巔其實已經(jīng)無所謂了。

簡單的說,這個思想最重要的是以業(yè)務(wù)領(lǐng)域為核心進(jìn)行發(fā)散,期望在變更程序的其他部分,不會影響到領(lǐng)域模型,也就是那句話為了“復(fù)雜的系統(tǒng)應(yīng)用程序中業(yè)務(wù)規(guī)則行為方式(就是“領(lǐng)域邏輯”)是會經(jīng)常變化的,我們要去擁抱這種變化”。結(jié)構(gòu)圖:

MVC的多層架構(gòu)怎么實現(xiàn)

CQRS:是指命令查詢職責(zé)的分離,是一個小的模式形態(tài),該模式的關(guān)鍵在于:“一個方法要么是用來改變某個對象的狀態(tài)的,要么就是返回一個結(jié)果,這兩者不會同時并存”。將整個系統(tǒng)分拆為兩個部分:

  • Commands(命令) - 改變某一個對象或整個系統(tǒng)的狀態(tài)(有時也叫做modifiers或者mutators)。

  • Queries(查詢) - 返回值并且不會改變對象的狀態(tài)。

架構(gòu)圖:

MVC的多層架構(gòu)怎么實現(xiàn)

不管DDD也好,CQRS也好,其實這兩種都不會100%適合所有的項目架構(gòu)的,這就需要架構(gòu)師結(jié)合項目本身特點及需求有所選擇,但是其中的思想我們可以運用在項目的任何地方。

基于消息的分布式:

其實不管使用怎樣的架構(gòu),加入怎樣的架構(gòu)思想(soa),核心或者是開發(fā)者最想達(dá)到的就是層次,系統(tǒng)之間的解耦,復(fù)雜的東西沒人會喜歡。

隨著系統(tǒng)的發(fā)展,我們的程序會涉及到多臺服務(wù)器,多種終端,同時為了解耦我們引入了基于消息的分布式架構(gòu)。

首先,所以系統(tǒng)的通信基于消息,邏輯聯(lián)系不會涉及到具體的業(yè)務(wù)實現(xiàn),同時消息的傳遞更加的廉價可適配多種終端。

其次,由于所用邏輯只是基于消息實現(xiàn),迭代的成本也會相對于其他耦合項目更快更方便。

MVC的多層架構(gòu)怎么實現(xiàn)

展示層:

隨之Web2.0的到來單一頁面展示的信息也更加的豐富,Ajax,js的流行也使得Ui端的操作也愈加變重,于是大家有期望以一種工程的思想去擁抱這種變化,于是MVVM,js的Mvc框架陸續(xù)出現(xiàn)。同時隨著移動互聯(lián)網(wǎng)的興起,不同終端對于系統(tǒng)的對接也非常重要,于是我們考慮在Ui與Logic之間引入Application或Service層應(yīng)對不同終端配置。

MVC的多層架構(gòu)怎么實現(xiàn)

如:我們在Client Presenter Layer 上加入WCF適配多種終端提交的訂單,都是建立在消息基礎(chǔ)之上的,樓主之前做電商系統(tǒng)是針對于來自淘寶,天貓,亞馬遜訂單時,為避免出現(xiàn)對庫中訂單并發(fā),產(chǎn)生“超買”情況,采用了在上層Ui與logic層之間引入了OrderChannel層,將不同終端訂單進(jìn)行排隊的解決方案。

以上是架設(shè)一個能夠適配不同需求的架構(gòu)過程,但是真正的真理是需要大家在實踐中,錯誤中汲取的。

下面是樓主簡單的小分層架構(gòu),不妥,不足之處希望大家指導(dǎo)斧正。

層次劃分:

MVC的多層架構(gòu)怎么實現(xiàn)

為了實現(xiàn)單獨部署,層次解耦所以層次之間是基于接口實現(xiàn)的。

DataAccess層引入倉儲實現(xiàn)統(tǒng)一DTO操作,實現(xiàn)基于Ef:

IRepository:

public interface IRepository<T> where T:class     {          IEnumerable<T> FindAll(Expression<Func<T,bool>> exp);          void Add(T entity);          void Delete(T entity);          void Submit();      }

引入RepositoryBase實現(xiàn)接口定義:

public class RepositoryBase<T>:IRepository<T> where T:class     {          DbContext context;          public RepositoryBase(DbContext _context)          {              context = _context;          }           public RepositoryBase() {              this.context = new TestDBEntities();          }           public IEnumerable<T> FindAll(Expression<Func<T, bool>> exp)          {              return context.Set<T>().Where(exp);          }           public void Add(T entity)          {              context.Set<T>().Add(entity);          }           public void Delete(T entity)          {              context.Set<T>().Remove(entity);          }           public void Submit()          {              context.SaveChanges();          }      }

這對于單一的某個倉儲我們單獨引入其自身的倉儲接口:

public interface IUserRepository:IRepository<UserTest>  {      IList<UserTest> GetAllById(int id);       bool CheckUserExist(UserTest u);  }

特定倉儲實現(xiàn):

public class UserRepository : RepositoryBase<UserTest>,IUserRepository      {          public IList<UserTest> GetAllById(int id)          {              using (TestDBEntities entities=new TestDBEntities())              {                  var users = from u in entities.UserTests                              where u.ID == id                              select u;                  return users.ToList();              }          }           public bool CheckUserExist(UserTest u)          {              using (TestDBEntities entities = new TestDBEntities())              {                  List<UserTest> users = entities.UserTests.Where(ut => ut.UserName == u.UserName && ut.UserPassword==u.UserPassword).ToList<UserTest>();                  return users.Count==0 ? false : true;              }          }      }

在Service層同樣建立相關(guān)接口適配特種服務(wù):

IUserCore:

public interface IUserCore      {          CommandStatueEnum UserLogin(IModel model);          CommandStatueEnum UserRegister(IModel model);           List<UserTest> GetUsers(Expression<Func<UserTest, bool>> expr);      }

UserCore:

public class UserCore : IUserCore      {          #region Structure          IUserRepository _repository;          public UserCore(IUserRepository repository) {              this._repository = repository;          }          #endregion           public CommandStatueEnum UserLogin(IModel model)          {              try             {                  UserLogin u = model as UserLogin;                  UserTest uTest = new UserTest();                  uTest.UserName = u.UserName;                  uTest.UserPassword = u.Password;                   if (_repository.CheckUserExist(uTest))                  {                      return CommandStatueEnum.Succeed;                  }                  else                 {                      return CommandStatueEnum.Fail;                  }              }              catch (Exception ex) {                  throw ex;              }          }           public CommandStatueEnum UserRegister(IModel model)          {              try             {                  UserLogin u = model as UserLogin;                  UserTest uTest = new UserTest() { UserName=u.UserName, UserPassword=u.Password};                  _repository.Add(uTest);                  _repository.Submit();                  return CommandStatueEnum.Succeed;              }              catch (Exception ex)              {                  throw ex;              }          }            public List<UserTest> GetUsers(System.Linq.Expressions.Expression<Func<UserTest, bool>> expr=null)          {             return _repository.FindAll(expr).ToList<UserTest>();          }      }

Controller:

public class AccountController : Controller      {          IUserCore userCore;          public AccountController(IUserCore _userCore)          {              this.userCore = _userCore;          }           //          // GET: /Account/           #region view          public ActionResult Home()          {              ViewBag.Users = userCore.GetUsers(u=>u.IsUse==1);              return View();          }           public ActionResult Login()          {              return View();          }           public ActionResult Register()          {              return View();          }          #endregion           #region Post          [HttpPost]          public ActionResult Login(UserLogin account)          {              try             {                  if (userCore.UserLogin(account) == CommandStatueEnum.Succeed)                  {                      return RedirectToAction("Home");                  }                  else                 {                      return View();                  }              }              catch (Exception ex)              {                  ExceptionModel.IsExcept = true;                  ExceptionModel.Exception = ex.ToString();                  ExceptionModel.CreateTime = DateTime.Now;                  return View();              }          }           [HttpPost]          public ActionResult Register(UserLogin account)          {              try             {                  if (userCore.UserRegister(account) == CommandStatueEnum.Succeed)                  {                      return RedirectToAction("Home");                  }                  else                 {                      return View();                  }              }              catch (Exception ex)              {                  ExceptionModel.IsExcept = true;                  ExceptionModel.Exception = ex.ToString();                  ExceptionModel.CreateTime = DateTime.Now;                  return View();              }          }          #endregion      }

對于接口之間我們通過引入IOC工具解耦:

public class MvcApplication : System.Web.HttpApplication      {          protected void Application_Start()          {              AreaRegistration.RegisterAllAreas();               WebApiConfig.Register(GlobalConfiguration.Configuration);              FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);              RouteConfig.RegisterRoutes(RouteTable.Routes);              BundleConfig.RegisterBundles(BundleTable.Bundles);              AuthConfig.RegisterAuth();               #region IOC              var builder = new ContainerBuilder();              SetupResolveRules(builder);              builder.RegisterControllers(Assembly.GetExecutingAssembly());              var container = builder.Build();              DependencyResolver.SetResolver(new AutofacDependencyResolver(container));              #endregion          }           private void SetupResolveRules(ContainerBuilder builder)          {              //Components are wired to services using the As() methods on ContainerBuilder              builder.RegisterType<UserCore>().As<IUserCore>();              builder.RegisterType<UserRepository>().As<IUserRepository>();          }       }

讀到這里,這篇“MVC的多層架構(gòu)怎么實現(xiàn)”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

mvc
AI