陳浩
摘要:ABP是“ASP.NET Boilerplate Project 即ASP.NET樣板項(xiàng)目”的簡(jiǎn)稱。ASP.NET Boilerplate是一個(gè)用最佳實(shí)踐和流行技術(shù)開發(fā)現(xiàn)代WEB應(yīng)用程序的新起點(diǎn),它旨在成為一個(gè)通用的WEB應(yīng)用程序框架和項(xiàng)目模板。ASP.NET Boilerplate 基于DDD領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的經(jīng)典分層架構(gòu)思想,實(shí)現(xiàn)了眾多DDD的概念。該文針對(duì)此問題討論了ABP的設(shè)計(jì)過程。
關(guān)鍵詞:ABP;ASP.NET;領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)
中圖分類號(hào):TP393 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2016)32-0045-02
1 ABP框架模式概述
ABP框架是基于ASP.NET的Web開發(fā)框架,不過它遵循一種名為DDD(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))的設(shè)計(jì)模式原則,下面就ABP框架的體系結(jié)構(gòu)及模塊系統(tǒng)做以分析。
為了減少復(fù)雜性和提高代碼的可重用性,采用分層架構(gòu)是一種被廣泛接受的技術(shù)。
為了實(shí)現(xiàn)分層的體系結(jié)構(gòu),ABP遵循DDD(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))的原則,將分為四個(gè)層次:
展現(xiàn)層(Presentation):提供一個(gè)用戶界面,實(shí)現(xiàn)用戶交互操作。
應(yīng)用層(Application):進(jìn)行展現(xiàn)層與領(lǐng)域?qū)又g的協(xié)調(diào),協(xié)調(diào)業(yè)務(wù)對(duì)象來執(zhí)行特定的應(yīng)用程序的任務(wù)。它不包含業(yè)務(wù)邏輯。
領(lǐng)域?qū)樱―omain):包括業(yè)務(wù)對(duì)象和業(yè)務(wù)規(guī)則,這是應(yīng)用程序的核心層。
基礎(chǔ)設(shè)施層(Infrastructure):提供通用技術(shù)來支持更高的層。例如基礎(chǔ)設(shè)施層的倉儲(chǔ)(Repository)可通過ORM來實(shí)現(xiàn)數(shù)據(jù)庫交互。
2 ABP體系結(jié)構(gòu)分析
一個(gè)簡(jiǎn)單的解決方案,大致包含5個(gè)項(xiàng)目,每一層可以用一個(gè)或多個(gè)程序集來實(shí)現(xiàn),具體分析如下:
1)領(lǐng)域?qū)樱―omain)
領(lǐng)域?qū)泳褪菢I(yè)務(wù)層,是一個(gè)項(xiàng)目的核心,所有業(yè)務(wù)規(guī)則都應(yīng)該在領(lǐng)域?qū)訉?shí)現(xiàn)。
2)實(shí)體(Entity)
實(shí)體代表業(yè)務(wù)領(lǐng)域的數(shù)據(jù)和操作,在實(shí)踐中,通過用來映射成數(shù)據(jù)庫表。
3)倉儲(chǔ)(Repository)
倉儲(chǔ)用來操作數(shù)據(jù)庫進(jìn)行數(shù)據(jù)存取。倉儲(chǔ)接口在領(lǐng)域?qū)佣x,而倉儲(chǔ)的實(shí)現(xiàn)類應(yīng)該寫在基礎(chǔ)設(shè)施層。
4)領(lǐng)域服務(wù)(Domain service)
當(dāng)處理的業(yè)務(wù)規(guī)則跨越兩個(gè)(及以上)實(shí)體時(shí),應(yīng)該寫在領(lǐng)域服務(wù)方法里面。
5)領(lǐng)域事件(Domain Event)
在領(lǐng)域?qū)幽承┨囟ㄇ闆r發(fā)生時(shí)可以觸發(fā)領(lǐng)域事件,并且在相應(yīng)地方捕獲并處理它們。
6)工作單元(Unit of Work)
工作單元是一種設(shè)計(jì)模式,用于維護(hù)一個(gè)由已經(jīng)被修改(如增加、刪除和更新等)的業(yè)務(wù)對(duì)象組成的列表。它負(fù)責(zé)協(xié)調(diào)這些業(yè)務(wù)對(duì)象的持久化工作及并發(fā)問題。
3應(yīng)用層(Application)設(shè)計(jì)
應(yīng)用層提供一些應(yīng)用服務(wù)(Application Services)方法供展現(xiàn)層調(diào)用。一個(gè)應(yīng)用服務(wù)方法接收一個(gè)DTO(數(shù)據(jù)傳輸對(duì)象)作為輸入?yún)?shù),使用這個(gè)輸入?yún)?shù)執(zhí)行特定的領(lǐng)域?qū)硬僮?,并根?jù)需要可返回另一個(gè)DTO。在展現(xiàn)層到領(lǐng)域?qū)又g,不應(yīng)該接收或返回實(shí)體(Entity)對(duì)象,應(yīng)該進(jìn)行DTO映射。一個(gè)應(yīng)用服務(wù)方法通常被認(rèn)為是一個(gè)工作單元(Unit of Work)。用戶輸入?yún)?shù)的驗(yàn)證工作也應(yīng)該在應(yīng)用層實(shí)現(xiàn)。ABP提供了一個(gè)基礎(chǔ)架構(gòu)使得很容易地實(shí)現(xiàn)輸入?yún)?shù)有效性驗(yàn)證。通過使用AutoMapper這樣的工具來進(jìn)行實(shí)體與DTO之間的映射。
4基礎(chǔ)設(shè)施層(Infrastructure)設(shè)計(jì)
當(dāng)在領(lǐng)域?qū)又袨槎x了倉儲(chǔ)接口,應(yīng)該在基礎(chǔ)設(shè)施層中實(shí)現(xiàn)這些接口??梢允褂肙RM工具,例如EntityFramework或NHibernate。ABP的基類已經(jīng)提供了對(duì)這兩種ORM工具的支持。數(shù)據(jù)庫遷移也被用于這一層。
5 WEB與展現(xiàn)層(Web & Presentation)設(shè)計(jì)
Web層使用ASP.NET MVC和Web API來實(shí)現(xiàn)??煞謩e用于多頁面應(yīng)用程序(MPA)和單頁面應(yīng)用程序(SPA)。
在SPA中,所有資源被一次加載到客戶端瀏覽器中(或者先只加載核心資源,其他資源懶加載),然后通過AJAX調(diào)用服務(wù)端WebApi接口獲取數(shù)據(jù),再根據(jù)數(shù)據(jù)生成HTML代碼。不會(huì)整個(gè)頁面刷新。現(xiàn)在已經(jīng)有很多SPA的JS框架,例如:AngularJs、DurandalJs、BackboneJs、EmberJs。 ABP可以使用任何類似的前端框架,但是ABP提供了一些幫助類,讓我們更方便地使用AngularJs和DurandalJs。
在經(jīng)典的多頁面應(yīng)用(MPA)中,客戶端向服務(wù)器端發(fā)出請(qǐng)求,服務(wù)器端代碼(ASP.NET MVC控制器)從數(shù)據(jù)庫獲得數(shù)據(jù),并且使用Razor視圖生成HTML。這些被生成后的HTML頁面被發(fā)送回客戶端顯示。每顯示一個(gè)新的頁面都會(huì)整頁刷新。
SPA和MPA涉及到完全不同的體系結(jié)構(gòu),也有不同的應(yīng)用場(chǎng)景。一個(gè)管理后臺(tái)適合用SPA,博客就更適合用MPA,因?yàn)樗诒凰阉饕孀ト ?/p>
SignalR是一種從服務(wù)器到客戶端發(fā)送推送通知的完美工具。它能給用戶提供豐富的實(shí)時(shí)的體驗(yàn)。
已經(jīng)有很多客戶端的Javascript框架或庫,JQuery是其中最流行的,并且它有成千上萬免費(fèi)的插件。使用Bootstrap可以讓我們更輕松地完成寫Html和CSS的工作。
ABP也實(shí)現(xiàn)了根據(jù)Web API接口自動(dòng)創(chuàng)建Javascript的代碼函數(shù),來簡(jiǎn)化JS對(duì)Web Api的調(diào)用。還有把服務(wù)器端的菜單、語言、設(shè)置等生成到JS端。(但是在我自己的項(xiàng)目中,我是把這些自動(dòng)生成功能關(guān)閉的,因?yàn)楸匾圆皇呛艽?,而這些又會(huì)比較影響性能)。
ABP會(huì)自動(dòng)處理服務(wù)器端返回的異常,并以友好的界面提示用戶。
6 ABP模塊系統(tǒng)設(shè)計(jì)過程
ABP框架提供了創(chuàng)建和組裝模塊的基礎(chǔ),一個(gè)模塊能夠依賴于另一個(gè)模塊。在通常情況下,一個(gè)程序集就可以看成是一個(gè)模塊。在ABP框架中,一個(gè)模塊通過一個(gè)類來定義,而這個(gè)類要繼承自AbpModule。
Assembly程序集:Assembly是一個(gè)包含來程序的名稱,版本號(hào),自我描述,文件關(guān)聯(lián)關(guān)系和文件位置等信息的一個(gè)集合。自己設(shè)計(jì)類庫生成的dll就可以看做是一個(gè)程序集,這個(gè)程序集可以包括很多類,類又包括很多方法等。
.net可以通過反射獲取一個(gè)程序集中的類以及方法。
例如開發(fā)一個(gè)可以在多個(gè)不同應(yīng)用中被調(diào)用MybolgApplication模塊,代碼如下:
public class MyBlogApplicationModule : AbpModule //定義
{
public override void Initialize() //初始化
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
//這行代碼的寫法基本上是不變的。它的作用是把當(dāng)前程序集的特定類或接口注冊(cè)到依賴注入容器中。
}
}
ABP框架會(huì)掃描所有的程序集,并且發(fā)現(xiàn)AbpModule類中所有已經(jīng)導(dǎo)入的所有類,如果已經(jīng)創(chuàng)建了包含多個(gè)程序集的應(yīng)用,對(duì)于ABP是為每一個(gè)程序集創(chuàng)建一個(gè)Module(模塊)。
生命期事件
在一個(gè)應(yīng)用中,abp框架調(diào)用了Module模塊的一些指定的方法來進(jìn)行啟動(dòng)和關(guān)閉模塊的操作??梢灾剌d這些方法來完成任務(wù)。
ABP框架通過依賴關(guān)系的順序來調(diào)用這些方法,假如:模塊A依賴于模塊B,那么模塊B要在模塊A之前初始化,模塊啟動(dòng)的方法順序如下:
PreInitialize-B
PreInitialize-A
Initialize-B
Initialize-A
PostInitialize-B
PostInitialize-A
下面是具體方法的說明:
1)PreInitialize
預(yù)初始化:當(dāng)應(yīng)用啟動(dòng)后,第一次會(huì)調(diào)用這個(gè)方法。在依賴注入注冊(cè)之前,可以在這個(gè)方法中指定自己的特別代碼。例如:假如創(chuàng)建了一個(gè)傳統(tǒng)的登記類,那么要先注冊(cè)這個(gè)類(使用IocManager對(duì)登記類進(jìn)行注冊(cè)),可以注冊(cè)事件到IOC容器。
2)Initialize
初始化:在這個(gè)方法中一般是來進(jìn)行依賴注入的注冊(cè),一般通過IocManager.RegisterAssemblyByConvention這個(gè)方法來實(shí)現(xiàn)。如果要實(shí)現(xiàn)自定義的依賴注入,那么需要使用依賴注入的相關(guān)文檔。
3)PostInitialize
提交初始化:最后一個(gè)方法,這個(gè)方法用來解析依賴關(guān)系。
4)Shutdown
關(guān)閉:當(dāng)應(yīng)用關(guān)閉以后,這個(gè)方法被調(diào)用。
7總結(jié)
目前.NET上有不少開源框架。比如Apworks和ABP。其中Apworks是中國(guó)人寫的一套開源框架。它是一個(gè)全功能的,不僅可以寫分布式應(yīng)用,也可以寫桌面應(yīng)用。ABP的全稱是Asp.Net boilerplate project(asp.net樣板工程)。是github上非常活躍的一個(gè)開源項(xiàng)目。它并沒有使用任何新的技術(shù),只是由兩名架構(gòu)師將asp.net開發(fā)中常用的一些工具整合到了一起,并且部分實(shí)現(xiàn)了DDD的概念。是一個(gè)開箱即用的框架,作為asp.net分布式應(yīng)用的一個(gè)良好起點(diǎn)。
參考文獻(xiàn):
[1] 仰燕蘭.ASP.NET AJAX框架研究及其在Web開發(fā)中的應(yīng)用[J].計(jì)算機(jī)應(yīng)用與軟件, 201l(6):195-198.
[2] 肖洋.基于ASP.NET的MVC框架的應(yīng)用開發(fā)模式研究[J].電子技術(shù)與軟件工程, 2016(2):63-63.
[3] 王素芳.基于多層架構(gòu)的ASP.NET 4 MVC框架研究[J].電腦與電信, 2015(10):64-66.
[4] 高欣.ASP.NET頁面間傳輸數(shù)據(jù)的幾種方法研究[J].軟件導(dǎo)刊,, 2012, 11(11):43-45.