• ShenNiu.MVC管理系统


    本篇将要和大家分享的是一个简单的后台管理系统,这里先发个地址http://www.lovexins.com:8081/(登陆账号:youke,密码:123123;高级用户账号:gaoji,密码:123123)有兴趣的各位可以先简单看下效果,此系统采用:Ace的h5样式+Mvc5.0 + redis+sqlserver+shenniu.pager.js构建完成,构建此项目初衷为了有一套自己现成的h5后台系统,为了以后能快速开发搭建一些系统;项目源码暂时不开源(完善后开源),如果您的确认可或者想研究下,可以扫博客下方二维码支持一下获取源码(哪怕1分钱都可),当然此文章主要目的不是为了广告,而是为了分享一些重要或者常用的代码处理方式,希望大家喜欢,多多支持:

     

    . Controller中使用自带生成的Dispose(bool)好与坏

    . List集合生成权限树

    . 对比集合,加载checkboxlist

    . 为啥使用redis来保存session

     

    下面一步一个脚印的来分享:

    . Controller中使用自带生成的Dispose(bool)好与坏

    首先,咋们先来看下mvc模板自动生成的Dispose重写方法:

    1        protected override void Dispose(bool disposing)
    2         {
    3             if (disposing)
    4             {
    5                 db.Dispose();
    6             }
    7             base.Dispose(disposing);
    8         }

    因为Controller实现了接口IDisposable,所以里面可以使用Dispose方法,再看db.dispose()这是用来释放连接数据库对象的,如果细心的朋友可以在调试的时候发现,我们在执行某个连接数据库操作后,退出action的时候会进入这个重新的Dispose方法中去,主要目的用来释放在Controller最上面生成的连接数据库对象,我这里是:

    看到这里个人觉吧这个对象放在这使用起来挺方便的,不过带来一个问题就是,如果在业务逻辑复杂的地方,直接使用这个db,直到最后执行完整个action退出Controller的时候才dispose释放连接会不会有问题,心中存疑,再加上前几天看了一篇博文,分享的内容大概有如此的字样:ef不需要使用using(原理也就是dispose)自己就能在操作完数据库后释放,原因底层已经实现了这个dispose;如此更让人感觉直接在Controller类下面申明数据库链接方便的很,但试为什么微软mvc模板Controller中会再自带一个dispose方法呢,这两种情况存在不排除的说法,当然今天的主要目的不是为了验证这两种到底哪个是对的,此文章暂时以自动生成的dispose为合理说法来分享内容(注:朋友们请勿抠字眼);

    一起来看,假如自动模板生成的全部靠Controller重写的这个dispose来释放数据连接,那么在多业务逻辑下,比如我在登陆的时候我们除了匹配唯一用户外,还需要记录获取权限树,加入redis的session储存其中等操作,不可能等这些操作完了再来释放数据连接,这样登陆用户多了一定会有问题吧,如果是这种情况的问题,或许只能通过在某处操作数据库后即时释放连接了;以上是格式观点和看法,或许有不妥之处,请联系指正,谢谢,特别是using真的不需要吗这个问题;

     

    . List集合生成权限树

    首先,我这里定义了一个固定的实体:

     /// <summary>
            /// 菜单类
            /// </summary>
            public class MoMenu
            {
    
                /// <summary>
                /// 菜单Id (必填)
                /// </summary>
                public int Id { get; set; }
    
                /// <summary>
                /// 名称
                /// </summary>
                public string Name { get; set; }
    
                /// <summary>
                /// 链接地址 (建议填写,每个需要登录访问的Action需要使用这个对比是否有权限)
                /// </summary>
                public string Link { get; set; }
    
                /// <summary>
                /// 描述
                /// </summary>
                public string Des { get; set; }
    
                /// <summary>
                /// 图标样式,对应StageClass.MoIcon
                /// </summary>
                public string Icon { get; set; }
    
                /// <summary>
                /// 排序(升序)
                /// </summary>
                public int Sort { get; set; }
    
                /// <summary>
                /// 父级菜单Id,最顶层父级默认0
                /// </summary>
                public int ParentId { get; set; }
    
                /// <summary>
                /// 是否导航栏
                /// </summary>
                public bool IsMenu { get; set; }
    
                /// <summary>
                /// 菜单子级集合
                /// </summary>
                public List<MoMenu> ListMenu { get; set; }
            }
    View Code

    主要用来装系统中所有菜单的数据,并且区分层级关系,然后通过如下方法:

     1 /// <summary>
     2         /// List集合生成菜单树
     3         /// </summary>
     4         /// <typeparam name="T">对比选中菜单的对象</typeparam>
     5         /// <param name="html"></param>
     6         /// <param name="list">系统全部菜单(需要有层级关系)</param>
     7         /// <param name="name">生成的checkboxlist的name</param>
     8         /// <param name="checkList">选中菜单的集合</param>
     9         /// <param name="defValFiled">选中匹配的默认值</param>
    10         /// <param name="isEnable">是否启用(查看状态不需要启用)</param>
    11         /// <param name="nLoop">循环层次(可能多余的吧)</param>
    12         /// <returns></returns>
    13         public static MvcHtmlString CheckBoxMenuByList<T>(
    14             this HtmlHelper html,
    15             List<StageModel.MoMenu> list,
    16             string name = "RadStatus",
    17             IEnumerable<T> checkList = null,
    18             string defValFiled = "Id",
    19 
    20             bool isEnable = true,
    21             int nLoop = 0)
    22             where T : class ,new()
    23         {
    24             var sbHtml = new StringBuilder(string.Empty);
    25             sbHtml.AppendFormat("<ul class='divmenu' style="list-style:none;{0}">", nLoop <= 0 ? "display:block" : "display:none");
    26             foreach (var item in list)
    27             {
    28                 var isCheck = false;
    29                 if (checkList != null)
    30                 {
    31                     foreach (var checkItem in checkList)
    32                     {
    33                         var ty = checkItem.GetType();
    34                         var val = ty.GetProperty(defValFiled).GetValue(checkItem, null);
    35                         isCheck = val.ToString().Equals(item.Id.ToString());
    36                         if (isCheck) { break; }
    37                     }
    38                 }
    39 
    40                 sbHtml.Append("<li>");
    41                 sbHtml.AppendFormat("<input id="{0}{1}" name="{0}" type="checkbox" value="{1}" {3} {4}/><label>{2}<b>{5}</b></label>",   // class="arrow fa fa-angle-down"
    42                     name,
    43                     item.Id,
    44                     item.Name,
    45                     isCheck ? "checked="checked"" : "",
    46                     isEnable ? "" : "disabled="disabled"",
    47 
    48                     item.ListMenu == null ? "" : (item.ListMenu.Count > 0 ? string.Format("[{0}]", item.ListMenu.Count) : "")
    49                     );
    50                 if (item.ListMenu == null) { sbHtml.Append("</li>"); continue; }
    51                 if (item.ListMenu.Count > 0)
    52                 {
    53                     sbHtml.Append(CheckBoxMenuByList(html, item.ListMenu, name, checkList, defValFiled, isEnable, isCheck ? 0 : nLoop++));
    54                 }
    55                 sbHtml.Append("</li>");
    56             }
    57             sbHtml.Append("</ul>");
    58             return MvcHtmlString.Create(sbHtml.ToString());
    59         }

    遍历生成菜单树,功能有:1.在查看状态即可使其禁用选择,2.编辑状态匹配对象选中菜单;然后需要在试图中增加如js代码:

    1 $("ul[class='divmenu'] li input[type='checkbox']").on("click", function () {
    2 
    3             var isCheck = $(this).is(":checked");
    4             //子级
    5             $(this).nextAll("ul").find("li input[type='checkbox']").prop("checked", isCheck);
    6         });
    7         $("ul[class='divmenu'] li label").on("click", function () {
    8             $(this).next("ul[class='divmenu']").toggle("normal");
    9         });

    最后,只需要在需要用到该菜单树的地方添加代码如: @Html.CheckBoxMenuByList(Stage.Com.Extend.StageClass.GetAllMenus(), "MenuIds", Model.MoRoleAndMenus, "MenuId") 即可,看到的效果图:

    具体大家可以登陆ShenNiu.MVC试试效果

     

    . 对比集合,加载checkboxlist

    首先,直接贴代码如:

     1 /// <summary>
     2         /// 对比集合,加载checkboxlist
     3         /// </summary>
     4         /// <typeparam name="T">目标对象</typeparam>
     5         /// <param name="html"></param>
     6         /// <param name="orgList">目标集合</param>
     7         /// <param name="orgFiledVal">目标对应checkbox的value值的属性名称</param>
     8         /// <param name="orgFiledText">对应的checkbox文本的text值的属性名称</param>
     9         /// <param name="destList">匹配集合</param>
    10         /// <param name="destFiled">匹配列的属性名称</param>
    11         /// <param name="sClass">样式</param>
    12         /// <param name="name">checkboxlist的Name</param>
    13         /// <returns></returns>
    14         public static MvcHtmlString CheckBoxRoleByList<T, TT>(
    15             this HtmlHelper html,
    16             IEnumerable<T> orgList,
    17             string orgFiledVal,
    18             string orgFiledText,
    19 
    20             IEnumerable<TT> destList = null,
    21             string destFiled = "",
    22 
    23             string sClass = "",
    24             string name = "cbAll")
    25             where T : class ,new()
    26             where TT : class,new()
    27         {
    28             var sbHtml = new StringBuilder(string.Empty);
    29             if (orgList.Count() <= 0) { return MvcHtmlString.Create(string.Empty); }
    30 
    31             sbHtml.AppendFormat("<div class="{0}">", sClass);
    32             foreach (var item in orgList)
    33             {
    34                 var ty = item.GetType();
    35                 var val = ty.GetProperty(orgFiledVal).GetValue(item, null);
    36                 var text = ty.GetProperty(orgFiledText).GetValue(item, null);
    37 
    38                 var isMatch = false;
    39                 if (destList != null)
    40                 {
    41                     foreach (var destItem in destList)
    42                     {
    43                         var destty = destItem.GetType();
    44                         var destval = destty.GetProperty(destFiled).GetValue(destItem, null);
    45 
    46                         if (val.ToString().ToUpper().Equals(destval.ToString().ToUpper()))
    47                         {
    48                             isMatch = true;
    49                             break;
    50                         }
    51                     }
    52                 }
    53                 sbHtml.AppendFormat("<label><input type='checkbox' name='{0}' value='{1}' {3} />{2}</label>", name, val, text, isMatch ? "checked='checked'" : "");
    54             }
    55             sbHtml.Append("</div>");
    56             return MvcHtmlString.Create(sbHtml.ToString());
    57         }

    使用编辑页面的效果图如:

    看到效果是默认绑定了该用户对应的权限“高级用户”,代码需要重点是:

    1  var ty = item.GetType();
    2  var val = ty.GetProperty(orgFiledVal).GetValue(item, null);
    3  var text = ty.GetProperty(orgFiledText).GetValue(item, null);

    主要作用就是指定特定的属性,获取特定属性的value值;item是List集合中的某个对象,具体参数说明可以看下代码备注;

     

    . 为啥使用redis来保存session

    这个小标题不好定义,我个人的见解,大家可以看看罢了;1:redis存储数据可以设置失效时间,这就类似于session失效的效果一样,所以redis能很好的来当做session容器;2:用上面一点我们可以再增加nginx等分布式服务,以此来打架一个分布式架构,这样在更新子系统的时候不会造成所以的业务瘫痪,可以不对用户的操作造成阻碍,仿佛没有更细过一样;3:基于redis搭建session服务器后session服务器这个时候可以单独分到另外一台服务器上,这样减少了内存占有率,应用程序和session分布多个服务器,大大提高承载率,不至于说什么千万级别就把您系统cpu爆满了,session还各种丢失的情况;4.使用redis打架服务后可以利用剩余空间存储一些不长变动的数据和消息,列如:系统中的菜单栏,一些消息提醒,邮件发送等数据,都可以使用其保存;

    以上是个人的观点和总结,希望能对大家有帮助;由于本人经验有限,如有不合理的地方请多多指正,谢谢。

  • 相关阅读:
    梯度下降(Gradient Descent)
    Positioning-Based Photo Retrieval
    NTU Long-Term Positioning Dataset
    Pycharm导入tabula模块包
    MySQL学习笔记20
    MySQL学习笔记17-19
    Android studio 报错AAPT2 error
    MySQL学习笔记13-16
    MySQL学习笔记 8-12
    机器学习十大算法
  • 原文地址:https://www.cnblogs.com/wangrudong003/p/6165949.html
Copyright © 2020-2023  润新知