ABP+AdminLTE+Bootstrap Table權限管理系統一期
Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS
前往博客園總目錄:ABP+AdminLTE+Bootstrap Table權限管理系統一期
說了這么久,還沒有詳細說到abp框架,abp其實基于DDD(領域驅動設計)原則的細看分層如下:
再看我們項目解決方案如下:
- 應用層(Application):應用層:進行展現層與領域層之間的協調梦谜,協調業(yè)務對象來執(zhí)行特定的應用程序的任務袭景。它不包含業(yè)務邏輯,主要包含一些模型,abp重要的數據傳輸DTO,包括數據庫映射實體,前端視圖模型轉實體(Entity)對象,一個應用服務方法通常被認為是一個工作單元(Unit of Work),使用一種像AutoMapper這樣的工具來進行實體與DTO之間的映射,前端參數傳入有限性驗證等等
- 領域層(Domain):領域層:領域層就是業(yè)務層,是一個項目的核心荒澡,所有業(yè)務規(guī)則都應該在領域層實現与殃。包括業(yè)務對象和業(yè)務規(guī)則碍现,這是應用程序的核心層米奸。
- 實體(Entity):實體代表業(yè)務領域的數據和操作,在實踐中慢睡,通過用來映射成數據庫表铡溪。
- 倉儲(Repository):倉儲用來操作數據庫進行數據存取。倉儲接口在領域層定義髓涯,而倉儲的實現類應該寫在基礎設施層哈扮。
- 領域服務(Domain service):當處理的業(yè)務規(guī)則跨越兩個(及以上)實體時,應該寫在領域服務方法里面育八。
- 領域事件(Domain Event): 在領域層某些特定情況發(fā)生時可以觸發(fā)領域事件赦邻,并且在相應地方捕獲并處理它們。
- 工作單元(Unit of Work):工作單元是一種設計模式按声,用于維護一個由已經被修改(如增加恬吕、刪除和更新等)的業(yè)務對象組成的列表铐料。它負責協調這些業(yè)務對象的持久化工作及并發(fā)問題。****
- 基礎設施層(Infrastructure):基礎設施層:提供通用技術來支持更高的層柒凉。例如基礎設施層的倉儲(Repository)可通過ORM來實現數據庫交互篓跛。當在領域層中為定義了倉儲接口,應該在基礎設施層中實現這些接口蔬咬。可以使用ORM工具林艘,例如EntityFramework或NHibernate北启。ABP的基類已經提供了對這兩種ORM工具的支持拔第。還有數據遷移等。
- 展現層(Presentation):**展現層:提供試圖用于與用戶實現交互操作.
- JCmsErp.WebApi:這里在abp中主要是提供接口,可以是解決方案內部使用接口,可以是與移動端等其他端口連接的接口.
二懈涛,實體(Entity)
實體是DDD(領域驅動設計)的核心概念之一泳猬。Eirc Evans是這樣描述的實體的:“它根本上不是通過屬性定義的,而是通過一系列連續(xù)性和標識定義的”埋心。因此忙上,實體都有Id屬性并且都存儲到數據庫中。一個實體一般會映射到數據庫的一張表
abp中實體是派生于Entity類茬斧,先看一下我們在Core層新建的Users類
- Users實體類项秉,有人說這個實體為什么沒有id,因為Users繼承自Entity類慷彤,Entity類已經定義id,
它是該Entity類的 主鍵贷屎。因此艘虎,所有實體的主鍵名都是相同的,都是Id属划。 - Id(主鍵)的類型是可以改變的,默認是int(int32)的绽昼。如果你想將Id定義為其他類型须蜗,可以在<>內寫,比如Guid,long也是可以的。
Entity類重寫了等號運算符(==)菱农,可以輕松地檢查兩個實體是否相同了(實體的Id相同則認為它們相同)柿估。它也定義了IsTransient方法來檢測它是否有Id。
審計:
- IHasCreationTime使得使用一個通用的屬性來描述一個實體的“創(chuàng)建時間”信息成為可能。當實現了該接口的實體類插入到數據庫中時足陨,ABP會自動地將當前的時間設置給CreationTime墨缘。
- ICreationAudited增加了CreatorUserId擴展了IHasCreationTime,當用戶保存一個新的實體的時候飒房,會自動把當前的id設置為CreatorUserId狠毯,還有類似的LastModificationTime也是一樣。
當更新實體時嚼松,abp會自動為你設置這些屬性献酗。
軟刪除
軟刪除是將一個實體標記為已刪除的通常使用的模式,而不是直接從數據庫中刪除很澄。比如,你可能不想從數據庫中硬刪除一個User甩苛,因為它可能關聯其他的表
ABP實現了開箱即用的軟刪除模式讯蒲。當一個軟刪除實體被刪除后,ABP檢測到之后赁酝,會阻止刪除旭等,將IsDeleted設置為true并更新數據庫中的實體。而且肪笋,它會自動地過濾數據庫中軟刪除的實體度迂,不會檢索(select)它們猜揪。
如果使用了軟刪除而姐,那么你可能想存儲一些信息拴念,比如何時刪除以及誰刪除了一個實體等等
在JCmsErp.Application創(chuàng)建一個Users文件夾,然后創(chuàng)建UserinfoDto,DTO是用于Core和 Web間的數據傳輸對象.有了實體了為什么還要DTO呢
- DTO保證了層與層的分離,web層改變不影響core層,core做改變也不影響web.
- 數據保護,不然敏感或者不需要的數據暴露于web層,不被別人窺見如密碼,銀行賬號,身份證等敏感信息
- 序列化,序列化集合,但是子集不序列化,當首次用到子集的時候才序列化.
- 惰性加載
- DTO數據驗證
- abp還有一些擴展的接口,擴展性好,降低耦合度,使表現層和邏輯層之間耦合度降低.
這里Serializable就是支持序列化的標簽, [AutoMapFrom(typeof(Users))]
是指和Users之間雙向自動轉化的標簽,并不需要每個字段都去手動匹配.ABP提供了若干特性和擴展方法來定義映射政鼠。首先,要將Abp.AutoMapper nuget包添加到項目中万搔。然后官帘,AutoMap特性是雙向映射方式, AutoMapFrom和 AutoMapTo是單向映射方式酗捌。最后,使用MapTo擴展方法將一個對象映射到另一個對象
ABP模塊系統簡介
ABP框架提供了創(chuàng)建和組裝模塊的基礎馅巷,一個模塊能夠依賴于另一個模塊草姻。在通常情況下,一個程序集就可以看成是一個模塊敞曹。在ABP框架中综膀,一個模塊通過一個類來定義剧劝,而這個類要繼承自AbpModule。
模塊系統當前專注于服務端而不是客戶端拢锹。
譯者注:
如果學習過Orchard的朋友萄喳,應該知道m(xù)odule模塊的強大了。模塊的本質就是可重用性充坑,你可以在任意的地方去調用染突,而且通過實現模塊,你寫的模塊也可以給別人用也榄。.net可以通過反射獲取一個程序集中的類以及方法薪棒。
1.3.2 定義模塊
Assembly程序集:Assembly是一個用來包含程序的名稱俐芯,版本號,自我描述邮辽,文件關聯關系和文件位置等信息的一個集合。最簡單的理解就是:一個你自己寫的類庫生成的dll就可以看做是一個程序集吨述,這個程序集可以包括很多類揣云,類又包括很多方法等。
一個派生自 AbpModule 的類就是模塊的定義刘莹。我們正在開發(fā)一個博客模塊焚刚,該模塊可以被使用在不同的應用程序中。最簡單的模塊定義示例如下:
public class MyBlogApplicationModule : AbpModule //定義
{
public override void Initialize() //初始化
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
//這行代碼的寫法基本上是不變的抢肛。它的作用是把當前程序集的特定類或接口注冊到依賴注入容器中碳柱。
}
}
如果需要的話,模塊類負責類的依賴注入(通呈看希可以像上面一樣做)猛蔽。我們能配置應用程序和其它模塊,添加新的功能到應用程序等等区岗。
1.3.3 方法的生命周期
在一個應用中毁枯,ABP框架調用了Module模塊的一些指定的方法來進行啟動和關閉模塊的操作。我們可以重載這些方法來完成我們自己的任務藐鹤。
ABP框架通過依賴關系的順序來調用這些方法赂韵,假如:模塊A依賴于模塊B,那么模塊B要在模塊A之前初始化祭示,模塊啟動的方法順序如下:
- PreInitialize-B
- PreInitialize-A
- Initialize-B
- Initialize-A
- PostInitialize-B
- PostInitialize-A
下面是具體方法的說明:
PreInitialize
預初始化:當應用啟動后,第一次運行會先調用這個方法稠歉。在初始化(Initialize)方法調用之前,該方法通常是用來配置框架以及其它模塊带饱。
在依賴注入注冊之前阅羹,你可以在這個方法中指定你需要注入的自定義啟動類灯蝴。例如:加入你創(chuàng)建了某個符合約定的注冊類,你應該使用 IocManager.AddConventionalRegisterer 方法在這里注冊它耕肩。
Initialize
初始化:在這個方法中一般是來進行依賴注入的注冊问潭,一般我們通過IocManager.RegisterAssemblyByConvention這個方法來實現。如果你想實現自定義的依賴注入梳虽,那么請參考依賴注入的相關文檔灾茁。
PostInitialize
提交初始化:最后一個方法北专,這個方法用來解析依賴關系。
Shutdown
關閉:當應用關閉以后语婴,這個方法被調用驶睦。
1.3.4 模塊依賴
Abp框架會自動解析模塊之間的依賴關系,但是我們還是建議你通過重載GetDependencies方法來明確的聲明依賴關系缠导。
[DependsOn(typeof(MyBlogCoreModule))]//通過注解來定義依賴關系
public class MyBlogApplicationModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}
例如上面的代碼酬核,我們就聲明了MyBlogApplicationModule和MyBlogCoreModule的依賴關系,MyBlogApplicationModule這個應用模塊依賴于MyBlogCoreModule核心模塊举瑰,并且蔬螟,MyBlogCoreModule核心模塊會在MyBlogApplicationModule模塊之前進行初始化。
ABP可以從 startup module 遞歸的解析依賴關系耸序,并按需初始化它們鲁猩。最后初始化的模塊是啟動模塊(startup module)廓握。
1.3.5 插件模塊
當模塊從啟動模塊以及其依賴關系進行調查發(fā)現的時候,ABP也能夠動態(tài)的加載其它指定模塊男应。AbpBootstrapper 類定義了 PlugInSources 屬性娱仔,我們能用該屬性添加需要動態(tài)加載的模塊牲迫。插件源可以是任何實現了 IPlugInSource 接口的類。FolderPlugInSource 類實現了該接口隔箍,它可以被用來加載指定文件夾下的程序集脚乡。
ASP.NET Core
ABP的ASP.NET Core模塊也可以動態(tài)加載模塊滨达,你只需要在 Startup 類中使用已定義的擴展方法 AddAbp捡遍,如下所示:
services.AddAbp<MyStartupModule>(options =>
{
options.PlugInSources.Add(new FolderPlugInSource(@"C:\MyPlugIns"));
});
我們可以使用擴展方法 AddFolder 更方便的實現上述功能:
services.AddAbp<MyStartupModule>(options =>
{
options.PlugInSources.AddFolder(@"C:\MyPlugIns");
});
了解更多關于Startup類的信息,請查看 ASP.NET 文檔
ASP.NET MVC辆飘,Web API
對于經典的ASP.NET MVC應用,我們可以在 global.asax 重寫 Application_Start 方法來添加插件文件夾芹关,如下所示:
public class MvcApplication : AbpWebApplication<MyStartupModule>
{
protected override void Application_Start(object sender, EventArgs e)
{
AbpBootstrapper.PlugInSources.AddFolder(@"C:\MyPlugIns");
//...
base.Application_Start(sender, e);
}
}
插件中的控制器
如果你的模塊包括了MVC或者Web API控制器侥衬,ASP.NET不能發(fā)現這些控制器跑芳。為了克服這個問題,你可以在 global.asax 中添加代碼來實現怀樟,如下所示:
using System.Web;
using Abp.PlugIns;
using Abp.Web;
using MyDemoApp.Web;
[assembly: PreApplicationStartMethod(typeof(PreStarter), "Start")]
namespace MyDemoApp.Web
{
public class MvcApplication : AbpWebApplication<MyStartupModule>
{
}
public static class PreStarter
{
public static void Start()
{
//...
MvcApplication.AbpBootstrapper.PlugInSources.AddFolder(@"C:\MyPlugIns\");
MvcApplication.AbpBootstrapper.PlugInSources.AddToBuildManager();
}
}
}
Additional Assemblies
對于IAssemblyFinder和ITypeFinder的默認實現(這兩個接口的實現被ABP用來在應用程序中發(fā)現指定的類)僅僅只用來查找模塊程序集以及在這些程序集中所使用的類型漂佩。我們可以在我們的模塊中重寫 GetAdditionalAssemblies 方法來包含附加程序集罪塔。
1.3.6 自定義的模塊方法
我們自己定義的模塊中可能有方法被其他依賴于當前模塊的模塊調用征堪,下面的例子,假設模塊2依賴于模塊1庸娱,并且想在預初始化的時候調用模塊1的方法谐算。這樣洲脂,就把模塊1注入到了模塊2,因此往果,模塊2就能調用模塊1的方法了一铅。
譯者注:
ABP的模塊系統與Orchard的模塊有類似之處,但還是有比較大的差別肮之。Orchard的框架修改了ASP.NET程序集的默認加載方式(模塊的DLL沒有放在Bin文件夾下,是放在WEB項目根文件夾下面的Modules文件夾下)眶明,實現了功能模塊的熱插拔赘来,而ABP的模塊程序集還是放在Bin文件夾下的凯傲,沒有實現熱插拔。
public class MyModule1 : AbpModule
{
public override void Initialize() //初始化模塊
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());//這里幌缝,進行依賴注入的注冊涵卵。
}
public void MyModuleMethod1()
{
//這里寫自定義的方法荒叼。
}
}
[DependsOn(typeof(MyModule1))]
public class MyModule2 : AbpModule
{
private readonly MyModule1 _myModule1;
public MyModule2(MyModule1 myModule1)
{
_myModule1 = myModule1;
}
public override void PreInitialize()
{
_myModule1.MyModuleMethod1(); //調用MyModuleMethod1的方法被廓。
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}
在這里,我們通過構造函數注入MyModule1到MyModule2昆婿,所以MyModule2能夠調用MyModule1的自定義方法蜓斧。當且僅當MyModule2依賴于MyModule1才是可能的挎春。
1.3.7 模塊配置
雖然自定義模塊可以被用來配置模塊,但是狼荞,作者建議使用啟動配置來定義和配置模塊帮碰。
1.3.8 模塊生命周期
所有的模塊類都被自動的注冊為單例模式殉挽。
返回簡書總目錄:ABP+AdminLTE+Bootstrap Table權限管理系統一期
前往博客園總目錄:ABP+AdminLTE+Bootstrap Table權限管理系統一期