您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“MVC的多層架構怎么實現”,內容詳細,步驟清晰,細節處理妥當,希望這篇“MVC的多層架構怎么實現”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
多層架構是開發人員在開發過程當中面對復雜且易變的需求采取的一種以隔離控制為主的應對策略,關于多層架構的標準,我認為有一句話是比較有代表性的“每一層都可以單獨部署”,最傳統,最簡單的就是從三層開始的:
將整個項目自下而上的分為:數據持久(數據訪問)層,邏輯(業務)層,UI(展現)層。
數據訪問層:負責將數據持久化響應的數據存儲設備上,如DataBase,Txt,Excel等。
業務邏輯層:負責處理為滿足軟件需求而訂制的一系列的邏輯與業務,如用戶在前端下訂單之后,整個業務流可能涉及到,獲取用戶信息,獲取商品信息,獲取購物車信息,驗證商品可購買數量是否滿足本次購買,針對用戶身份產生不同的優惠策略,同時會驗證Cookie,Session等端產生數據的有效性,最終才會產生訂單,而訂單產生之后會涉及到倉儲物流等一系列的Erp系統業務,所有的這一套都屬于“下訂單”這一需求的業務邏輯。
展示層:負責與用戶交互的界面,良好的用戶體驗多是使用在這里。
學習過Petshop的話,對于三層都不會陌生:
但是隨著業務的復雜每一層都會有自己的進化,最終有了無數附加在三層之上的框架與開發思想。
首先我一直認為這兩種事屬于展現層的,“展現層MCV”,“展現層MVP”。
然后我們站在展現層的角度思考一下“Mvc”與“MVP”。
Mvc:分為model,Controller,View,相信大家對于他已經很熟悉了,在此不再累述。
MVP:MVP有Model-Presenter-View三個層次
其實在樓主最開始接觸Mvc的時候,就在想如果直接通過Controller與Model交互是不是顯得有一些“不干凈”,因為在樓主眼里“展現層的Controller”,做得最多的應該就是對于請求路由的不同響應與調用,但是很多的例子會將一些數據驗證,去糟的操作過程放在Controller中,顯得不倫不類。當MVP出現的時候,一切滿足了樓主的幻想,P的過程就是滿足了這一需求,P起到中介的作用,負責接收視圖請求,再把結果映射到view上,P可以不對View做強引用,可通過IView適配多個view。當然我也會在這里做一些針對于終端數據的驗證與過濾。
從描述上可以看的很清楚,整個自上而下的結構,最復雜,最可能失控的就是業務邏輯層,因為其中包含著許多的不可控因素,每個行業領域的需求都有可能包含自身的領域知識。于是在之后的多層架構發展構成當中,更多的變化與智慧是體現在這里。
領域驅動:限于本人才學不能在這里分享太多,以防誤導大家,想了解更多可參考園子里的其他大牛,其實沒有3,5年相關經驗是很難理解的,個人感覺如果你不理解的話也不會對你有什么影響,因為領域驅動是建立在良好的面相對象分析,邊界劃分基礎之上的,在學習的過程當中已經能幫助你去學習到足夠多的知識了,最終到不到山巔其實已經無所謂了。
簡單的說,這個思想最重要的是以業務領域為核心進行發散,期望在變更程序的其他部分,不會影響到領域模型,也就是那句話為了“復雜的系統應用程序中業務規則行為方式(就是“領域邏輯”)是會經常變化的,我們要去擁抱這種變化”。結構圖:
CQRS:是指命令查詢職責的分離,是一個小的模式形態,該模式的關鍵在于:“一個方法要么是用來改變某個對象的狀態的,要么就是返回一個結果,這兩者不會同時并存”。將整個系統分拆為兩個部分:
Commands(命令) - 改變某一個對象或整個系統的狀態(有時也叫做modifiers或者mutators)。
Queries(查詢) - 返回值并且不會改變對象的狀態。
架構圖:
不管DDD也好,CQRS也好,其實這兩種都不會100%適合所有的項目架構的,這就需要架構師結合項目本身特點及需求有所選擇,但是其中的思想我們可以運用在項目的任何地方。
其實不管使用怎樣的架構,加入怎樣的架構思想(soa),核心或者是開發者最想達到的就是層次,系統之間的解耦,復雜的東西沒人會喜歡。
隨著系統的發展,我們的程序會涉及到多臺服務器,多種終端,同時為了解耦我們引入了基于消息的分布式架構。
首先,所以系統的通信基于消息,邏輯聯系不會涉及到具體的業務實現,同時消息的傳遞更加的廉價可適配多種終端。
其次,由于所用邏輯只是基于消息實現,迭代的成本也會相對于其他耦合項目更快更方便。
隨之Web2.0的到來單一頁面展示的信息也更加的豐富,Ajax,js的流行也使得Ui端的操作也愈加變重,于是大家有期望以一種工程的思想去擁抱這種變化,于是MVVM,js的Mvc框架陸續出現。同時隨著移動互聯網的興起,不同終端對于系統的對接也非常重要,于是我們考慮在Ui與Logic之間引入Application或Service層應對不同終端配置。
如:我們在Client Presenter Layer 上加入WCF適配多種終端提交的訂單,都是建立在消息基礎之上的,樓主之前做電商系統是針對于來自淘寶,天貓,亞馬遜訂單時,為避免出現對庫中訂單并發,產生“超買”情況,采用了在上層Ui與logic層之間引入了OrderChannel層,將不同終端訂單進行排隊的解決方案。
以上是架設一個能夠適配不同需求的架構過程,但是真正的真理是需要大家在實踐中,錯誤中汲取的。
下面是樓主簡單的小分層架構,不妥,不足之處希望大家指導斧正。
為了實現單獨部署,層次解耦所以層次之間是基于接口實現的。
DataAccess層引入倉儲實現統一DTO操作,實現基于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實現接口定義:
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); }
特定倉儲實現:
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層同樣建立相關接口適配特種服務:
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的多層架構怎么實現”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。