国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

領域驅動設計實戰(zhàn)—基于DDDLite的權限管理OpenAuth.net

2019-11-14 14:25:09
字體:
來源:轉載
供稿:網友

        在園子里面,搜索一下“權限管理”至少能得到上千條的有效記錄。記得剛開始工作的時候,寫個通用的權限系統(tǒng)一直是自己的一個夢想。中間因為工作忙(其實就是懶!)等原因,被無限期擱置了。最近想想,自己寫東西時,很多都是偏理論方面的,常常找不到合適的例子來論證自己的觀點。于是用業(yè)余時間來寫點東西。

園子中的權限管理系統(tǒng)有以下幾種:

  1. 寫的好的,界面NB的,但不開源,畢竟人家辛辛苦苦的勞動成果;
  2. 寫的好的,也公開源碼,但不公開數(shù)據(jù)庫設計和一些流程設計,你得看著源碼去猜字段去猜流程;
  3. 不定期講源碼和放截圖的,丫的就是不放出項目的,這種同1,就是沒事?lián)Q個馬甲來水點廣告;
  4. 入門級的,開放源碼的,但那源碼實在是不想多看兩眼;

什么也不說了,開干!文字太多了,來個動態(tài)圖緩一緩:

screen

需求

        首先,做個東西必須要把需求搞清楚。園子里面的權限管理需求分析的比較合理的,應該是蕭秦的我的權限系統(tǒng)設計實現(xiàn)MVC4 + WebAPI + EasyUI + Knockout(一) ,具體總結如下:

1、權限資源
    a.菜單權限  經理和業(yè)務員登陸系統(tǒng)擁有的功能菜單是不一樣的
    b.按鈕權限  經理能夠審批,而業(yè)務員不可以
    c.數(shù)據(jù)權限  A業(yè)務員看不到B業(yè)務員的單據(jù)
    d.字段權限  某些人查詢客戶信息時看不到客戶的手機號或其它字段

2、用戶,應用系統(tǒng)的具體操作者,我這里設計用戶是不能直接分配權限的,必須要分配一個角色,角色中再分配權限,如果某個用戶權限比較特殊,可以為他專門建一個角色來應用解決,因為如果用戶也可以分配權限系統(tǒng)就會復雜很多。【我采用的還是可以直接給用戶分配菜單/按鈕,畢竟我們的人員就喜歡搞些特殊待遇】

3、角色,為了對許多擁有相似權限的用戶進行分類管理,定義了角色的概念,以上所有的權限資源都可以分配給角色,角色和用戶N:N的關系。

4、機構,樹形的公司部門結構,國內公司用的比較多,它實際上就是一個用戶組,機構和用戶設計成N:N的關系,也就是說有時候一個用戶可以從屬于兩個部門,這種情況在我們客戶需求中的確都出現(xiàn)過。

設計

        本來想用DDD(也就是把CQRS/AES等一堆的東西全用上,如果你想學習完整的DDD框架,可以參考我的另一個項目BestQ&A --開源中國推薦項目/集CQRS AES等DDD高級特性于一體的問答系統(tǒng))實現(xiàn)這個項目,思考再三還是被自己否定了。畢竟自己也在學習真正的領域驅動設計,思想上不是很成熟。再者,我相信對于普通的經典DDD架構(好高大上的說,悄悄地告訴你其實就是分層分的格調不一樣!),我是有絕對的信心可以把控的。

與其他權限管理相同的地方

        使用了萬惡的EF+MVC結構,當然,我沒惡俗到用EasyUI,為了體現(xiàn)個性,選擇了酷炫的基于bootstrap的B-JUI前端(炫不炫,你說了算)。相同的東西總是無趣,你可以無視,請把注意力放在下面。

與其他權限管理不同的地方

1、項目采用經典DDD架構(用沃恩.弗農大神的話,其實這是DDD-Lite)思想進行開發(fā),簡潔而不簡單,實用至上,并且所寫每一行代碼都經過深思熟慮,采用Autofac對項目進行解耦,符合S.O.L.I.D規(guī)則!來秀一下內在美:

using OpenAuth.Domain;using OpenAuth.Domain.Interface;using System;using System.Collections.Generic;using System.Linq;namespace OpenAuth.App{    public class OrgManagerApp    {        PRivate IOrgRepository _repository;        public OrgManagerApp(IOrgRepository repository)        {            _repository = repository;        }        public IList<Org> GetAll()        {            return _repository.LoadOrgs().ToList();        }        /// <summary>        /// 部門的直接子部門        /// <para>TODO:可以根據(jù)用戶的喜好決定選擇LoadAllChildren或LoadDirectChildren</para>        /// </summary>        public IList<Org> LoadDirectChildren(int orgId)        {            return _repository.Find(u => u.ParentId == orgId).ToList();        }        /// <summary>        /// 得到部門的所有子部門        /// <para>如果orgId為0,表示取得所有部門</para>        /// </summary>        public IList<Org> LoadAllChildren(int orgId)        {            string cascadeId = "0.";            if (orgId != 0)            {                var org = _repository.FindSingle(u => u.Id == orgId);                if (org == null)                    throw new Exception("未能找到指定對象信息");                cascadeId = org.CascadeId;            }            return _repository.Find(u => u.CascadeId.Contains(cascadeId) && u.Id != orgId).ToList();        }        /// <summary>        /// 添加部門        /// </summary>        public int AddOrUpdate(Org org)        {            if (org.Id == 0)            {                ChangeModuleCascade(org);                _repository.Add(org);            }            else            {                _repository.Update(org);            }            return org.Id;        }        /// <summary>        /// 刪除指定ID的部門及其所有子部門        /// </summary>        public void DelOrg(int id)        {            var delOrg = _repository.FindSingle(u => u.Id == id);            if (delOrg == null) return;            _repository.Delete(u => u.CascadeId.Contains(delOrg.CascadeId));        }        #region 私有方法        //修改對象的級聯(lián)ID,生成類似XXX.XXX.X.XX        private void ChangeModuleCascade(Org org)        {            string cascadeId;            int currentCascadeId = 1;  //當前結點的級聯(lián)節(jié)點最后一位            var sameLevels = _repository.Find(o => o.ParentId == org.ParentId && o.Id != org.Id);            foreach (var obj in sameLevels)            {                int objCascadeId = int.Parse(obj.CascadeId.Split('.').Last());                if (currentCascadeId <= objCascadeId) currentCascadeId = objCascadeId + 1;            }            if (org.ParentId != 0)            {                var parentOrg = _repository.FindSingle(o => o.Id == org.ParentId);                if (parentOrg != null)                {                    cascadeId = parentOrg.CascadeId + "." + currentCascadeId;                    org.ParentName = parentOrg.Name;                }                else                {                    throw new Exception("未能找到該組織的父節(jié)點信息");                }            }            else            {                cascadeId = "0." + currentCascadeId;                org.ParentName = "根節(jié)點";            }            org.CascadeId = cascadeId;        }        #endregion 私有方法    }}

2、教科書級的分層思想,哪怕苛刻的你閱讀的是大神級經典大作(如:《企業(yè)應用架構模式》《重構與模式》《asp.net設計模式》等),你也可以參考本項目。不信?有圖為證,Resharper自動生成的項目引用關系,毫無PS痕跡!

architect

記得以前弦子哥寫過一篇園子里面搭構架對比的文章(.Net項目分層與文件夾結構大全(最佳架子獎,吐槽獎,陰溝翻船獎揭曉)),本想也建他10幾個項目,想一想還是算了,折騰讀的人也折騰我自己。畢竟我的項目還沒有分布式的需求,就算有,也得遵循分布式設計的最高準則------能不用分布式就不要用!

所以精簡到6個項目,個個都是精華!

所有項目都依賴于領域層,而領域層不關心任何數(shù)據(jù)庫實現(xiàn)或界面UI實現(xiàn);

通過依賴注入真正實現(xiàn)了上層與數(shù)據(jù)庫分離,雖然數(shù)據(jù)庫訪問采用了EF的方式,但WEB層對此毫不知情!

3、經過N次優(yōu)化的數(shù)據(jù)庫結構設計。本來數(shù)據(jù)庫核心表中有很多多對多的關系(用戶與機構/用戶與角色/角色與模塊等等),如下:

pdm1

代碼寫到一半的時候,覺得何苦呢,為什么以前設計權限的人都喜歡這么設計?去你的,看我的:

pdm2

瞬間少了很多,代碼風格也可以統(tǒng)一起來,多美好的事情啊。你會問:所有多對多關系放在一張表,性能怎么辦?什么?性能?沒有千萬級數(shù)據(jù),別和我提性能。如果你的系統(tǒng)幾十萬數(shù)據(jù)時都會很卡,還是去惡補一下數(shù)據(jù)庫基礎吧!

界面

人要臉樹要皮,沒圖沒真相!

login

add

 

user

Module

 

源碼及說明

 

項目地址:https://git.oschina.net/yubaolee/OpenAuth.Net

 

源碼中包含所有的程序代碼,數(shù)據(jù)庫PowerDesigner設計圖,CodeSmith生成模板,數(shù)據(jù)庫初始腳本。請下載源碼后,先用Nuget還原引用的第三方包,再修改一下web.config里面的連接字符串。

當前代碼已經實現(xiàn)核心功能如下:

  • 模塊/用戶/部門/角色的分級管理;
  • 為用戶分配角色或直接為用戶分配模塊;
  • 根據(jù)模塊URL地址與MVC的Controller適配授權;
  • 頁面菜單按鈕分配;
  • 內部已經集成log4net,只需要簡單的 LogHelper.Log("日志內容") 即可;

最近開發(fā)功能展望:

  • 菜單授權處理;
  • 數(shù)據(jù)權限處理;
  • 用戶分級授權功能;

 

短短一文怎么能表達完一個項目的功能與思想!在后續(xù)的博客中,我會結合自己對企業(yè)開發(fā)的一些看法,對DDD的一些看法,對重構的一些看法,等等等等,來講述自己的程序人生。

 

本博客其他精彩內容:http://www.survivalescaperooms.com/yubaolee/p/Catalogue.html


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 长武县| 齐齐哈尔市| 三明市| 易门县| 叶城县| 桑日县| 济南市| 贡嘎县| 洛南县| 吉林市| 寻乌县| 龙陵县| 美姑县| 芒康县| 浦北县| 大足县| 阿拉善左旗| 金湖县| 灵丘县| 三原县| 蒙城县| 纳雍县| 朝阳县| 陇西县| 铁岭县| 盐山县| 平潭县| 额济纳旗| 黄石市| 石棉县| 奈曼旗| 屯门区| 新晃| 锦屏县| 郯城县| 大兴区| 南充市| 新沂市| 巫山县| 衡阳县| 平陆县|