時間真快,轉眼今年又要過去了。回想今年,依次開源發佈了Colder.Fx.Net.AdminLTE(254Star)、Colder.Fx.Core.AdminLTE(335Star)、DotNettySocket(82Star)、IdHelper(47Star),這些框架及組件都是本着以實際出發,實事求是的態度,力求提升開發效率(我本身都是第一個使用者),目前來看反響不錯。可是隨着前端和後端技術的不斷變革,尤爲是前端,目前大環境已是先後端徹底分離爲主的開發模式,在這樣的大環境和必然趨勢之下,傳統的MVC就顯得有些落伍了。在這樣的背景下,一款先後端分離的.NET開發框架就顯得尤其必要,由此便定了框架的升級目標:先後端分離。html
首前後端技術的選擇,從目前的數據來看,.NET Core的發展遠遠快於.NET Framework,最簡單的分析就是Colder.Fx.Core.AdminLTE發佈比Colder.Fx.Net.AdminLTE晚,可是星星卻後來居上並且比前者多30%,而且這個差距在不斷擴大,由點及面的分析能夠看出咱們廣大.NET開發人員學習的熱情和積極向上的態度,並非某些人所認爲的那麼不堪(走本身的路,讓別人說去吧)。大環境上微軟積極擁抱開源,大力發展.NET Core, 能夠說前途一片光明。所以後端決定採用 .NET Core3.0 ,再也不浪費精力去支持.NET Framework。前端
而後是前端技術選擇,首選是三大js框架選擇,也是從實際出發,Vue相對其它而言更加容易上手,而且功能也絕不遜色,深得各類大小公司喜歡,若是偏要說缺點的話,那就是對TS支持不行,可是即將發佈Vue3.0確定會改變這一缺陷。選擇了Vue以後,而後就是UI框架的選擇了,這裏的選擇更多了,我選擇了Ant Design Vue,理由即是簡潔方便,十分符合個人設計理念。vue
技術選型完畢以後便進入研發,因爲鄙人前端比較菜,所以須要從頭學Vue2.x全家桶,從開始到如今差很少經歷3個月,在預期以內。其實學習並使用前端的Vue2.x全家桶並不難,仍是比較容易上手的,因此在此給沒有先後端分離開發經驗的老哥打一記預防針,不要退縮,要知難而上,學習永無止境。node
某些老哥可能比較直接粗暴,嫌我BBB嘮叨,下面直接上地址
代碼(GitHub):https://github.com/Coldairarrow/Colder.Admin.AntdVue
文檔(GitHub):https://github.com/Coldairarrow/Colder.Admin.AntdVue/wiki
代碼(碼雲鏡像):https://gitee.com/Coldairarrow/Colder.Admin.AntdVue
文檔(碼雲鏡像):https://gitee.com/Coldairarrow/Colder.Admin.AntdVue/wikis
在線預覽地址:http://coldairarrow.gitee.io/coler.antdvue.preview/#/Home/Introduce
因爲服務器是阿里雲的86服務器,帶寬1M小水管,所以將前端部署到碼雲上了,在此多謝碼雲,後端部署在阿里雲86服務器CentOS7上。整個技術棧使用.NET Core + PostggreSQL+ Ant Design Vue + CentOS7+Nginx+Dokcer+jenkins,囊虧了從快速開發到自動化部署一條龍,開源免費並具備高性能、高移植性、高拓展性(小公司創業選型+我的接單利器)git
本框架爲.NET Core3.0+Ant Design Vue版github
本框架旨在極大的提升開發效率算法
使用技術棧:
後端:採用.NET Core平臺,ASP.NET Core3.0,C#語言(使用反射等高級技術),Entity FrameworkCore(數據庫ORM框架)。
使用數據倉儲模式,抽象化數據庫操做(CRUD等)、支持事務處理以及分佈式事務處理(跨庫)
支持數據庫讀寫分離、分庫分表及事務(僅支持單表操做,不支持多表) 全面採用Autofac做爲IOC容器,面向接口編程,全面解耦
集成多種工具類庫以及操做拓展
數據庫:支持SqlServer,PostgreSQL,MySQL,Oracle(框架使用簡單工廠,工廠方法,抽象工廠,可輕鬆更換數據庫),Redis做爲分佈式緩存
前端:Vue2.x全家桶+Ant Design Vue,其中集成經常使用組件,力求方便項目開發。數據庫
具體技術實施:
項目採用先後端徹底分離模式,並採用嚴格分層模式,極大的增長聚合度,下降耦合度,
提升代碼的健壯性,可維護性。
先後端經過JWT進行身份驗證,經過數據接口操做數據,統一使用JSON做爲數據格式,並使用默認接口簽名算法保證接口的安全性。編程
功能架構部分詳解:
快速開發:此功能爲框架的核心,經過選擇數據庫中的表,就能自動生成對應的實體層、業務邏輯層、控制器、前端頁面Vue文件,無需編寫代碼便可生成基本的CRUD操做。
接口密鑰管理:管理接口的密鑰,若開啓接口簽名的規則,則前端須要經過給接口簽名纔可以正常訪問後臺接口。
權限管理:使用基本的RBAC權限控制,支持操做權限、接口權限以及數據權限json
框架主要功能及特點以下
功能 | 詳細描述 |
---|---|
用戶登陸 | 用戶登陸、密碼修改 |
系統用戶管理 | 系統用戶管理 |
角1色管理 | 角色管理 |
部門管理 | 部門管理、自然多級 |
權限管理 | 使用RBAC權限體系,基於角色的權限管理,支持菜單權限、操做權限(按鈕權限)、接口權限、數據權限 |
系統日誌 | 支持多彩控制檯、文件、數據庫和ElasticSearch記錄日誌,框架全局異常自動捕捉,多級別記錄 |
快速開發 | 經過數據庫直接生成實體層、業務邏輯層、控制器層以及前端頁面Vue代碼,無需編碼便可實現CURD |
數據庫操做封裝 | 使用基於EF的倉儲模式、封裝經常使用的CURD,支持單庫事物和分佈式事物 |
多數據庫支持 | 使用基於EF的倉儲模式,支持各大主流關係型數據庫(SQLServer、MySQL、PostgreSQL和Oracle) |
超強移植性 | 使用抽象工廠封裝數據庫操做層,切換數據庫0代碼修改 |
支持軟刪除 | 一鍵切換刪除模式,支持物理刪除和軟刪除,對業務操做透明 |
緩存支持 | 支持系統自帶緩存和Redis緩存、封裝操做接口、簡單易用 |
先後端徹底分離 | 前端使用Vue2.x全家桶+Ant Design Vue,界面簡潔美觀,組件化開發 |
集成JWT驗證 | 框架使用JWT做爲身份驗證,擺脫Cookie苦海,分佈式拓展毫無壓力 |
集成對外接口簽名算法 | 框架對外接口能夠開啓超強嚴格簽名校驗(防抵賴、防僞造、防重複調用),保障系統安全性 |
頁面響應式 | 前端爲單頁應用,無iframe,各大主流瀏覽器支持友好 |
拓展 | 其它各類幫助類庫及插件 |
其相關版本請看下錶:
.NET版本 | 前端UI | 地址 |
---|---|---|
Core3.0 | Ant Design Vue | https://github.com/Coldairarrow/Colder.Admin.AntdVue |
Core2.2 | AdminLTE | https://github.com/Coldairarrow/Colder.Fx.Core.AdminLTE |
.NET4.72 | AdminLTE | https://github.com/Coldairarrow/Colder.Fx.Net.AdminLTE |
.NET4.52 | Easyui | https://github.com/Coldairarrow/Coldairarrow.Fx.Net.Easyui.GitHub |
Core2.1 | Easyui | https://github.com/Coldairarrow/Coldairarrow.Fx.Core.Easyui.GitHub |
.NET4.0 | Easyui | https://github.com/Coldairarrow/Coldairarrow.Fx.Net40.Easyui.GitHub |
後臺效果展現以下:
操做系統:Windows 10
後端開發工具:Visual Studio 2019+
前端開發工具:Visual Studio Code,安裝nodejs,yarn
SDK:安裝.NET Core SKD 3.0 及以上
數據庫:SQLServer2008 R2及以上
以下圖所示依次展開05.Coldairarrow.Api/appsettings.json,配置數據庫鏈接字符串,name不用修改,connectionString改成上述建立的數據庫(若不清楚數據庫鏈接字符串請自行百度搜索教程)
因爲本框架支持自動生成代碼的核心功能,此功能是根據數據庫的表結構來生成代碼的
所以規定每張表都有一個主鍵,列名爲Id,類型爲字符串,實際添加數據時默認使用SnowflakeId(雪花Id,Twitter設計的分佈式趨勢自增Id,若不清楚請自行百度相關資料),表中的每一個列都須要有描述信息(建議這樣操做,若不按照這個標準則須要一些額外的改動纔可以成功運行)。每張表都須要Id、CreateTime、CreatorId、CreatorRealName這幾個必帶字段
後端:打開解決方案=>還原nuget包=>配置數據庫=>運行(05.Coldairarrow.Web設爲啓動項目)
後臺成功運行後會自動打開swagger
前端: 確保已安裝nodejs和yarn
用VS Code 打開文件夾src\Coldairarrow.Web
輸入命令:yarn
輸入命令:yarn run serve
成功運行後便可打開登陸頁面
輸入帳號:Admin,密碼:123456進入後臺主頁
在01.Coldairarrow.Util中的GlobalSwitch類中,設置了各個參數,其中RunModel與DatabaseType須要重點關注一下,其它參數請看註釋。
此功能爲本框架的核心功能,可以自動生產完整的可運行代碼,具體使用以下:
首選須要有數據庫源,由於代碼生成是根據數據庫表來生成的。
菜單:開發=>數據庫鏈接
若列表中沒有目標數據源,則添加數據庫鏈接
數據鏈接名、鏈接字符串、數據庫類型便可。添加完成後便可看到鏈接字符串信息。
有了數據庫鏈接以後,便可進行代碼生成。
菜單:開發=>代碼生成
選擇數據庫,而後勾選須要生成代碼的數據庫表,點擊生成代碼會彈出生成選項(這裏演示勾選 Base_BuildTest,其他表全是系統基礎表,不要勾選,不然會被覆蓋,致使異常,請勾選本身的業務表進行生成):
生成選項中能夠選擇須要生成的類型,默認生成所有:實體層、業務層、接口層(即控制器)和頁面(Vue前端頁面代碼)。
生成區域請輸入業務模塊名(例如系統叫Base_Manage),請按具體業務填入(必填)
這裏示例填寫TestManage,點擊生成按鈕,便可完成代碼生成。生成後的代碼在項目解決方案中,將代碼文件包括進入項目
默認生成後的文件會被自動包括到解決方案中,若沒有則須要點擊顯示全部文件按鈕,便可看到生成後的新文件
生成的實體層、業務邏輯層、控制器層代碼:
前端生成的代碼:
後端代碼添加後須要從新編譯下(F7),編譯後好能夠看到有新的接口
前端生成代碼後會自動保存並編譯(別的文件修改保存也會自動編譯,畢竟編譯一次挺慢的),不放心能夠Ctrl+C中止,而後再yarn run serve從新運行
代碼生成完畢,可是要展現到菜單上須要進行配置,而且全部業務菜單都是動態的(權限控制)
打開菜單:系統管理=>權限管理=>新建
菜單名:即須要顯示的菜單名
上級菜單:菜單是多級樹狀的,能夠放在某個菜單下面
類型:能夠選擇菜單或頁面,這裏是具體的頁面,因此選頁面
路徑:頁面的路徑,菜單能夠不配置,這裏配置爲/TestManage/Base_BuildTest/List,這裏設置規則爲:views文件夾爲根路徑(即"/"),向下展開依次爲/TestManage/Base_BuildTest/List,最後真正的列表頁爲List.vue文件,表單頁爲EditForm.vue文件
是否須要權限:若爲「否」,則此頁面不限制權限,即全部人都能看
圖標:菜單顯示圖標,具體到開發=>圖標選擇頁進行選擇
排序:若須要須要對菜單進行排序則設置,默認0,類型爲int
頁面權限:頁面擁有的權限(權限值惟一,做爲操做權限即接口權限的依據),詳見權限管理
確認保存,而後刷新整個頁面(F5),便可看到全新生成的菜單「生成測試」
整個代碼生成過程,無需編寫代碼便可完成一張表的CRUD,固然須要根據具體業務中進行相應的修改,本次示例中字段比較少,可是當一張表的字段不少時,那麼此功能可以將開發效率提升幾個檔次。
默認超級管理員帳號爲:Admin
密碼爲:123456
管理系統登陸的用戶
菜單:系統=>用戶管理
點擊右側設置權限
管理系統角色,角色是權限的載體,合理分配角色有利於權限管理
菜單:系統=>角色管理
操做中能夠設置角色的權限,詳情見 <權限管理> 模塊
通常狀況下,後臺管理系統多少會涉及權限管理,所以本框架提供了一個靈活、高效、簡潔的權限管理系統。
首先,權限分爲兩種,即操做權限和數據權限,其中操做權限主要包括菜單權限和按鈕權限,在角色編輯表單中,給角色勾選須要的權限便可,用戶能夠分配多個角色,繼承全部角色的權限。
如上圖,按需勾選,有人會疑問爲何只有增、改和刪的權限而沒有查的權限,其實這裏考慮到了當勾選「用戶管理」時,就已經默認擁有「查」的權限了,這裏再設置「查」權限豈不是畫蛇添足,能夠根據實際業務需求添加諸如申請、審覈等權限,靈活應用。
這裏的樹狀是和菜單一一對應的,勾選哪些菜單就擁有哪些菜單
下面介紹下最經常使用的按鈕權限
如上圖,在須要控制權限的按鈕使用v-if="hasPerm('Base_User.Add')",表示只有當用戶擁有權限值Base_User.Add才顯示此按鈕,權限值就是權限表單中配置的權限值
這裏的按鈕級權限控制只可以在前端控制操做入口,若系統對安全性要求較高,則須要控制接口權限
如上圖,在須要權限控制的接口加上ApiPermission特性便可,參數也爲權限值,只有擁有此權限才能訪問此接口
數據權限比較複雜,若採用純SQL方式,那麼會更加複雜,本框架全程採用EF做爲ORM框架,經過對IQueryable< T >進行過濾,便可完成數據權限控制,詳細使用方式見用戶管理。
更詳細的使用方式,請參考源代碼中的用戶管理模塊(菜單權限、操做權限、數據權限、聯表查詢、業務層AOP等使用方式都可參考此模塊)。
做爲對外接口簽名的AppId和AppSecret管理
菜單:系統=>接口祕鑰管理
菜單:系統=>系統日誌
使用方式以下:
BaseBusiness<Base_UnitTest> _baseBus = new BaseBusiness<Base_UnitTest>(); /*RunTransaction傳入執行具體數據庫操做的Action,操做中若出現異常會自動回滾事務,業務只需根據返回的transActionRes進行處理,返回類型爲元組(bool Success, Exception ex),Success表示事務是否成功,ex爲事務失敗異常信息*/ var transActionRes = _baseBus.RunTransaction(() => { var newData = _newData.DeepClone(); newData.Id = Guid.NewGuid().ToString(); newData.UserId = IdHelper.GetId(); newData.UserName = IdHelper.GetId(); _baseBus.Insert(_newData); _baseBus.Insert(newData); });
使用方式以下:
//第一個數據庫 IRepository _bus1 = DbFactory.GetRepository(); //另外一個數據庫 IRepository _bus2 = DbFactory.GetRepository("BaseDb_Test"); _bus1.DeleteAll<Base_UnitTest>(); _bus2.DeleteAll<Base_UnitTest>(); Base_UnitTest data1 = new Base_UnitTest { Id = Guid.NewGuid().ToString(), UserId = "1", UserName = Guid.NewGuid().ToString() }; Base_UnitTest data2 = new Base_UnitTest { Id = data1.Id, UserId = "1", UserName = Guid.NewGuid().ToString() }; Base_UnitTest data3 = new Base_UnitTest { Id = Guid.NewGuid().ToString(), UserId = "2", UserName = Guid.NewGuid().ToString() }; new Action(() => { //建立並執行事務,使用方式與單庫一致 var succcess = DistributedTransactionFactory.GetDistributedTransaction(_bus1, _bus2) .RunTransaction(() => { _bus1.ExecuteSql("insert into Base_UnitTest(Id) values('10') "); _bus1.Insert(data1); _bus1.Insert(data2); _bus2.Insert(data1); _bus2.Insert(data3); }); Assert.AreEqual(succcess.Success, false); Assert.AreEqual(_bus1.GetIQueryable<Base_UnitTest>().Count(), 0); Assert.AreEqual(_bus2.GetIQueryable<Base_UnitTest>().Count(), 0); })();
本框架支持數據庫讀寫分離分庫分表(即Sharding),而且支持主流關係型數據庫(SQLServer、Oracle、MySQL、PostgreSQL),理論上只要EF支持那麼本框架支持。
因爲技術緣由以及結合實際狀況,目前本框架僅支持單表的Sharding,即支持單表的CRUD、分頁、統計(數量、最大值、最小值、平均值),支持跨庫(表分散在不一樣的數據庫中,不一樣類型數據庫也支持)。具體如何使用以下:
ShardingConfigBootstrapper.Bootstrap() //添加數據源 .AddDataSource("BaseDb", DatabaseType.SqlServer, dbBuilder => { //添加物理數據庫 dbBuilder.AddPhsicDb("BaseDb", ReadWriteType.ReadAndWrite); }) //添加抽象數據庫 .AddAbsDb("BaseDb", absTableBuilder => { //添加抽象數據表 absTableBuilder.AddAbsTable("Base_UnitTest", tableBuilder => { //添加物理數據表 tableBuilder.AddPhsicTable("Base_UnitTest_0", "BaseDb"); tableBuilder.AddPhsicTable("Base_UnitTest_1", "BaseDb"); tableBuilder.AddPhsicTable("Base_UnitTest_2", "BaseDb"); }, new ModShardingRule("Base_UnitTest", "Id", 3)); });
上述代碼中完成了Sharding的配置:
ShardingConfigBootstrapper.Bootstrap()在一個項目中只能執行一次,因此建議放到Application_Start中(ASP.NET Core中的Startup)
AddDataSource是指添加數據源,數據源能夠看作抽象數據庫,一個數據源包含了一組同類型的物理數據庫,即實際的數據庫。一個數據源至少包含一個物理數據庫,多個物理數據庫須要開啓主從複製或主主複製,經過ReadWriteType(寫、讀、寫和讀)參數來指定數據庫的操做類型,一般將寫庫做爲主庫,讀庫做爲從庫。同一個數據源中的物理數據庫類型相同,表結構也相同。
配置好數據源後就能夠經過AddAbsDb來添加抽象數據庫,抽象數據庫中須要添加抽象數據表。如上抽象表Base_UnitTest對應的物理表就是Base_UnitTest_0、Base_UnitTest_1與Base_UnitTest_2,而且這三張表都屬於數據源BaseDb。分表配置固然須要分表規則(即經過一種規則找到具體數據在哪張表中)。
上述代碼中使用了最簡單的取模分片規則,
源碼以下:
能夠看到其使用方式及優缺點。
另外還有一致性HASH分片規則
雪花Id的mod分片規則
上述的分片規則各有優劣,都實現IShardingRule接口,實際上只須要實現FindTable方法便可實現自定義分片規則。
實際使用中我的推薦使用雪花Id的mod分片規,這也是爲何前面數據庫設計規範中默認使用雪花Id做爲數據庫主鍵的緣由(PS,以前版本使用GUID做爲主鍵被各類嫌棄,此次看大家怎麼說)
IShardingRepository _db = DbFactory.GetRepository().ToSharding();
而後便可進行數據操做:
Base_UnitTest _newData = new Base_UnitTest { Id = Guid.NewGuid().ToString(), UserId = "Admin", UserName = "超級管理員", Age = 22 }; List<Base_UnitTest> _insertList = new List<Base_UnitTest> { new Base_UnitTest { Id = Guid.NewGuid().ToString(), UserId = "Admin1", UserName = "超級管理員1", Age = 22 }, new Base_UnitTest { Id = Guid.NewGuid().ToString(), UserId = "Admin2", UserName = "超級管理員2", Age = 22 } }; //添加單條數據 _db.Insert(_newData); //添加多條數據 _db.Insert(_insertList); //清空表 _db.DeleteAll<Base_UnitTest>(); //刪除單條數據 _db.Delete(_newData); //刪除多條數據 _db.Delete(_insertList); //刪除指定數據 _db.Delete<Base_UnitTest>(x => x.UserId == "Admin2"); //更新單條數據 _db.Update(_newData); //更新多條數據 _db.Update(_insertList); //更新單條數據指定屬性 _db.UpdateAny(_newData, new List<string> { "UserName", "Age" }); //更新多條數據指定屬性 _db.UpdateAny(_insertList, new List<string> { "UserName", "Age" }); //更新指定條件數據 _db.UpdateWhere<Base_UnitTest>(x => x.UserId == "Admin", x => { x.UserId = "Admin2"; }); //GetList獲取表的全部數據 var list=_db.GetList<Base_UnitTest>(); //GetIQPagination獲取分頁後的數據 var list=_db.GetIShardingQueryable<Base_UnitTest>().GetPagination(pagination); //Max var max=_db.GetIShardingQueryable<Base_UnitTest>().Max(x => x.Age); //Min var min=_db.GetIShardingQueryable<Base_UnitTest>().Min(x => x.Age); //Average var min=_db.GetIShardingQueryable<Base_UnitTest>().Average(x => x.Age); //Count var min=_db.GetIShardingQueryable<Base_UnitTest>().Count(); //事務,使用方式與普通事務一致 bool succcess = _db.RunTransaction(() => { _db.Insert(_newData); var newData2 = _newData.DeepClone(); _db.Insert(newData2); }).Success; Assert.AreEqual(succcess, false);
上述操做中表面上是操做Base_UnitTest表,實際上卻在按照必定規則使用Base_UnitTest_0~2三張表,使分片對業務操做透明,極大提升開發效率
具體使用方式請參考單元測試源碼:
"\src\Coldairarrow.UnitTests\DataRepository\ShardingTest.cs"
框架使用EF+LINQ進行聯表操做,核心在於對IQueryable< T >的使用,另可網上搜EF+LINQ的相關教程。
示例以下:
Base_User表左鏈接Base_Department表獲取DepartmentName屬性
//定義數據模型類 public class Base_UserTestDTO : Base_User { public string DepartmentName { get; set; } } //即BaseBusiness中的Service var db = DbFactory.GetRepository(); Expression<Func<Base_User, Base_Department, Base_UserTestDTO>> select = (a, b) => new Base_UserTestDTO { DepartmentName = b.Name }; select = select.BuildExtendSelectExpre(); var q = from a in db.GetIQueryable<Base_User>().AsExpandable() join b in db.GetIQueryable<Base_Department>() on a.DepartmentId equals b.Id into ab from b in ab.DefaultIfEmpty() select @select.Invoke(a, b); //篩選 var where = LinqHelper.True<Base_UserTestDTO>(); where = where.And(x => x.UserName == "Admin"); //篩選並獲取分頁數據 var list = q.Where(where).GetPagination(new Pagination()).ToList();
源碼可參考Base_UserBusiness.GetDataList
在01.Coldairarrow.Util項目中的GlobalSwitch,將DatabaseType改成須要的便可,對應的數據庫鏈接字符串固然也要改成對應數據庫的
在具體的Business類中重寫父類BaseBusiness的構造函數便可,按照本身的需求重寫對應的構造函數,同時須要確保數據庫鏈接字符串已添加
若須要同時使用多個數據庫,或者須要多線程操做數據庫,須要使用
歡迎使用本框架,若以爲不錯,請比心
Github歡迎星星:https://github.com/Coldairarrow
博客園歡迎點贊:https://www.cnblogs.com/coldairarrow/
QQ羣2:579202910
我的QQ:862520575(歡迎技術支持及商務合做,提供.NET Core + Linux + Nginx+ jenkins + git整套持續集成快速開發平臺)
本人將會對這個快速開發框架不斷完善與維護,但願可以幫助到各位
若遇到任何問題或須要技術支持,請聯繫我。
------學習永無止境,技術永無上限,代碼就是藝術------