bootstrap加载mysql数据库_bootstrap后台管理系统前后台实现(含数据库)

撰写本文档目的是让后续开发者在理解该系统架构的基础上遵循一定规范保持系统架构的合理性;同时也能够达到允许没有开发经验仅有web基础的入门开发者能够通过复制粘贴的方式仿照demo示例进行开发的目的。

目  录

1       案例调研与选取... 2

1.1      案例调研... 2

1.2      UI选取... 3

2       系统实现... 3

2.1      实现效果... 3

2.2      开发规范... 6

3       详细设计... 7

3.1      框架介绍... 7

3.2      数据库设计... 8

3.3      菜单管理... 8

3.4      权限管理/角色管理... 11

3.5      权限管理/权限分配... 13

3.6      权限管理/用户管理... 14

4       延伸思考... 14

5       致谢! 14

6       文档说明... 15

7       参考文献... 15

案例调研与选取

案例调研

1)easyUI(No1)

图片

2)easyUI(No2)

图片

3)Bootstrap

图片

4)vue/iview

图片

以上四套UI框架对比分析,可以得出如下结论

结论:

easyUI功能完善,界面简洁友好,非常方便后端开发人员开发,是优秀的前端开源框架,尤其适合后台管理,但是非响应式,页面不会随屏幕大小而变化,美观方面(仁者见仁);

bootstrap是响应式开源框架,支持插件广泛,界面相对酷炫,美观方面(有目共睹),同样也非常适合管理平台的开发;

至于Vue和其它一些前端人员自己写的UI框架,必须要承认Vue是不错的开源框架,但是个人感觉对管理平台来说Vue增加了开发人员的学习成本、兼容性、美观等方面的调试成本,开发周期偏长,至于是否适合管理品台开发就……;

综上分析,对于管理平台开发建议选用easyUI或基于bootstrap搭建好的管理平台,本文选择基于bootstrap的管理平台进行说明。

UI选取

经过调研,选取了一套业内好评率较高的UI(ace-master),

Ace是一个基于Twitter bootstrap3开发的后台模板。

GitHub Ace地址:https://github.com/bopoda/ace

Ace演示:http://ace.jeka.by/

主体界面如下:

此框架功能多多,详细功能请看演示。

系统实现

实现效果

登录

2)首页

3)以下是权限管理的具体模块

开发规范

下图为框架的三个区域,其中主面板区域采用为一个div(没有采用iframe设计),每个菜单的内容均会更新主面板区域,故在主面板区域内容需要遵循一定的规范:

建议每个一级菜单在一个包中,每个包中的二级菜单均为一个单独的控制器。建议页面也需按同样方式设计。每个页面中的字段必须全局唯一(very import)

每个页面中的字段可采用驼峰式也可用下划线式,但必须确保每个页面以及下面多级页面中的每个字段名必须不同(即使业务上为同一张表的同一个字段),不可在模态框与主面板区用同一个页面。(如此设计的原因是:由于主页面采用div设计,故为防止js检测异常)

(important)由于主面板区域采用div设计,父页面(main.jsp)中已经有了

故子页面面不要引入这个js了(也无需引入),否则会引起密码修改的模态框无法弹出;

如果想要引入的话,请修改密码修改的模态框弹出效果。

命名规范示例:

每个页面中字段命名(包括方法名、表单字段、div等元素的id等):  模块名+页面名+数据库字段名

示例:userManageListAccountName

或者    user_manage_list_account_name

这样组成了全局唯一字段,防止浏览器缓存导致的页面插件功能异常和表单提交异常等问题;

详细设计

框架介绍

1)页面布局

页面布局见开发规范中截图,三个主要区域。

2)功能

功能上主要为权限管理和其它的项目相关的开发人员自定义的菜单模块。前后端交互采用ajax技术,页面核心的公共区域的交互在

;该文件中封装了菜单url调用和菜单效果切花、主面板区域更新的ajax、菜单树的动态加载、解析、拼装等功能。

3)权限

权限管理中包括用户管理、菜单管理、角色管理、权限分配和密码修改。

4)菜单加载

用户状态为启用时可登录到系统,进入到主板面后根据用户对应角色查找相应的菜单加载到菜单区域,从而实现不同角色的用户能够看到不同的菜单权限。

5)插件

框架中整合的插件主要如下(部分):

Bootstrap-table、bootstrap-datetimepicker、jquery.gritter(右上角弹框插件)、bootstrap-treeview、bootstrap-switch、jQuery.ui(确认框)。

其中datetimepicker样式似乎并没有想象中的好,需要进一步确认原因还是切换其它插件,如果对样式要求不高可临时使用,但考虑到后续扩展,故而建议尽快确认(修复or更换)。

数据库设计

数据库中权限管理模块设计了用户表、角色表、菜单表、用户角色关联表、角色菜单关联表,共计5张表,sql代码详见数据库文件。

用户表:

角色表:

菜单表:

用户角色关联表:

角色菜单关联表:

菜单管理

菜单包括主页面菜单区域的菜单也包含“权限管理à菜单管理”中的菜单。

1)主页菜单封装:

菜单表设计,见数据库设计。

菜单最大设计四级菜单,拼装的json格式(下文为大致示例,以实际为准);

读取库中菜单信息,拼接采用何种算法?

方案一:循环遍历,多重循环遍历

方案二:递归

此处选择递归,原因一是效率高(内存需要或许也高,完全可容忍),二是不受限于菜单级别,

递归核心代码如下(详见源码)

/**

* 递归查找子菜单

* @param id

* @param rootMenu

* @return

*/

private List getChilds(Long id, List rootMenu){

// 子菜单

List childList = new ArrayList();

Iterator it = rootMenu.iterator();

while(it.hasNext()) {

SysMenu menu = it.next();

// 遍历所有节点,将父菜单id与传过来的id比较

if (String.valueOf(menu.getLong("menu_pa_id")).equals(String.valueOf(id))){

Map mapcc = new HashMap();

mapcc.put("id", menu.getLong("id"));

mapcc.put("menu_name", menu.getStr("menu_name"));

mapcc.put("menu_url", menu.getStr("menu_url"));

childList.add(mapcc);

it.remove();

}

}

// 把子菜单的子菜单再循环一遍

for (Map map : childList) {

//递归

map.put("childMenus", getChilds(Long.parseLong(map.get("id").toString()), rootMenu));

}

//递归退出条件

if (childList.size() == 0) {

return null;

}

return childList;

}

拼接得到json菜单格式为(如下为二级菜单示例,其它详见源码、界面操作):

{

"status":"200",

"data":[

{

"id":1,

"childMenus":null,

"menu_url":"/manage/systemInfo.do",

"menu_name":"系统信息"

},

{

"id":2,

"childMenus":[

{

"id":5,

"childMenus":null,

"menu_url":"/redis/main.do",

"menu_name":"查询redis"

},

{

"id":6,

"childMenus":null,

"menu_url":"/redis/writeRdisPage.do",

"menu_name":"写redis"

}

],

"menu_url":null,

"menu_name":"redis管理"

},

{

"id":3,

"childMenus":[

{

"id":7,

"childMenus":null,

"menu_url":null,

"menu_name":"榴莲短视频"

},

{

"id":8,

"childMenus":null,

"menu_url":"/haohuolab/haohuoPage.do",

"menu_name":"东龙实验室"

}

],

"menu_url":null,

"menu_name":"东龙实验室"

},

{

"id":4,

"childMenus":[

{

"id":9,

"childMenus":null,

"menu_url":"/system/users/userPages.do",

"menu_name":"用户管理"

},

{

"id":10,

"childMenus":null,

"menu_url":null,

"menu_name":"角色管理"

},

{

"id":11,

"childMenus":null,

"menu_url":null,

"menu_name":"权限分配"

},

{

"id":12,

"childMenus":null,

"menu_url":null,

"menu_name":"菜单管理"

},

{

"id":13,

"childMenus":null,

"menu_url":"/manage/updatePwdPages.do",

"menu_name":"密码修改"

}

],

"menu_url":null,

"menu_name":"权限管理"

}

],

"msg":"success"

}

2)菜单解析

上面是拼接菜单代码,下面是解析菜单代码:

解析菜单的时候踩了一个坑,就是二级菜单在浏览器端始终无法打开,反复调试到晚上十一二点始终不知道什么原因,第二天来了之后继续调试,最终发现是a标签上缺少了一个属性(class='dropdown-toggle'),有时可能就是很小的一个问题让你耽误很长很长的时间还弄的自己焦头烂额,深感有时阻碍你前进的可能不是那万里征程(搭建整套完善框架),却可能是脚下的一粒沙子。

废话少说,直接上递归核心代码(实际略有改动,详见源码):

/**

* 递归遍历子树

* @param list

*/

function mainPageRecurSubTree(ctx,list){

if(null==list || ""==list || "null"==list){

return "";

}

var mainPageRecurSubTreeStr = "";

mainPageRecurSubTreeStr +=

"

for(var m=0;m

var menuSub = list[m];

mainPageRecurSubTreeStr +=

"

"+

""+

""+

menuSub.menu_name;

if(null!=menuSub.childMenus && ""!=menuSub.childMenus && "null"!=menuSub.childMenus){

mainPageRecurSubTreeStr +=

"";

}

mainPageRecurSubTreeStr +=

""+

""+

mainPageRecurSubTree(ctx,menuSub.childMenus)+

"";

}

mainPageRecurSubTreeStr +=

"

";

return mainPageRecurSubTreeStr;

}

3)权限管理/菜单管理

菜单插件采用bootstrap-treeview插件,

开关按钮采用bootstrap-switch插件;注意:将所需的开关插件放入到main.jsp中,开关样式方可正常引用,否则如果放到每个功能模块的子页面中会导致插件无法完全加载而导致的样式显示的问题。

菜单管理页面中添加根菜单,也可添加子菜单,选择/修改菜单的上级菜单,修改菜单信息等功能。

权限管理/角色管理

权限管理à角色管理:

角色管理中的菜单权限修改(修改角色对应的菜单信息):

也采用了bootstrap-TreeView插件,但是此原生的树菜单没有级联选项,故添加级联选择的js,核心代码如下:

//级联选择:选中

$("#roleManageUpdateRoleMenuAllTreeMes").on('nodeChecked',function(event,node){

roleManageUpdateRoleMenuNodeChecked(event, node);;

});

//级联选择:取消选中

$("#roleManageUpdateRoleMenuAllTreeMes").on('nodeUnchecked',function(event,node){

roleManageUpdateRoleMenuNodeUnchecked(event, node);;

});

//如下是响应菜单选中和取消选中的操作

var roleManageUpdateRoleMenuNodeCheckedSilent = false;

function roleManageUpdateRoleMenuNodeChecked(event, node){

if(roleManageUpdateRoleMenuNodeCheckedSilent){

return;

}

roleManageUpdateRoleMenuNodeCheckedSilent = true;

roleManageUpdateRoleMenuCheckAllParent(node);

roleManageUdpateRoleMenuCheckAllSon(node);

roleManageUpdateRoleMenuNodeCheckedSilent = false;

}

var roleManageUpdateRoleMenuNodeUncheckedSilent = false;

function roleManageUpdateRoleMenuNodeUnchecked(event, node){

if(roleManageUpdateRoleMenuNodeUncheckedSilent){

return;

}

roleManageUpdateRoleMenuNodeUncheckedSilent = true;

roleManageUpdateRoleMenuUncheckAllParent(node);

roleManageUpdateRoleMenuUncheckAllSon(node);

roleManageUpdateRoleMenuNodeUncheckedSilent = false;

}

//选中全部父节点

function roleManageUpdateRoleMenuCheckAllParent(node){

$("#roleManageUpdateRoleMenuAllTreeMes").treeview('checkNode',node.nodeId,{silent:true});

var parentNode = $("#roleManageUpdateRoleMenuAllTreeMes").treeview('getParent',node.nodeId);

if(!("nodeId" in parentNode)){

return;

}else{

roleManageUpdateRoleMenuCheckAllParent(parentNode);

}

}

//取消全部父节点

function roleManageUpdateRoleMenuUncheckAllParent(node){

$("#roleManageUpdateRoleMenuAllTreeMes").treeview('uncheckNode',node.nodeId,{silent:true});

var siblings = $("#roleManageUpdateRoleMenuAllTreeMes").treeview('getSiblings', node.nodeId);

var parentNode = $("#roleManageUpdateRoleMenuAllTreeMes").treeview('getParent',node.nodeId);

if(!("nodeId" in parentNode)) {

return;

}

var isAllUnchecked = true;  //是否全部没选中

for(var i in siblings){

if(siblings[i].state.checked){

isAllUnchecked=false;

break;

}

}

if(isAllUnchecked){

roleManageUpdateRoleMenuUncheckAllParent(parentNode);

}

}

//级联选中所有子节点

function roleManageUdpateRoleMenuCheckAllSon(node){

$("#roleManageUpdateRoleMenuAllTreeMes").treeview('checkNode',node.nodeId,{silent:true});

if(node.nodes!=null&&node.nodes.length>0){

for(var i in node.nodes){

roleManageUdpateRoleMenuCheckAllSon(node.nodes[i]);

}

}

}

//级联取消所有子节点

function roleManageUpdateRoleMenuUncheckAllSon(node){

$("#roleManageUpdateRoleMenuAllTreeMes").treeview('uncheckNode',node.nodeId,{silent:true});

if(node.nodes!=null&&node.nodes.length>0){

for(var i in node.nodes){

roleManageUpdateRoleMenuUncheckAllSon(node.nodes[i]);

}

}

}

权限管理/权限分配

权限管理à权限分配:为不同用户分配不同角色。

在权限分配è角色分配  页面中,使用了一个多选框的插件(用于选择多个角色),如下图:

在使用中发现这个选择框第一次打开时正常,之后再打开始终不正常,调试发现是因为select中动态添加了一个div并且这个div的style=“width:0px”;导致select的展示出现问题。试了各种方式,网上搜了各种方案均失败。最终万般无奈之下猜想可能是引用的js文件中生成这个内部div时导致宽度获取的问题,于是便修改引用的js源码,修改如下:

至此问题解决。

问:如何知道要修改这个宽度(如何定位到是要修改这个宽度的)?

答:在浏览器中调试时发现在select中生成的div的id是在select的id的基础之上添加了“_chosen”,于是搜索“_chosen”发现整个js源码中只有一个“_chosen”,于是在此附近寻找width相关的代码,终于发现了并尝试修改成功。

权限管理/用户管理

权限管理à用户管理:功能为对能够登录到系统的管理用户的增、查、修改、停用操作。

此页面中的table采用bootstrap原生表格,增改查的逻辑完全为自己实现。没有使用bootstrap-table插件。

本系统设计者建议使用bootstrap-table插件(why? 我也不知道,就是感觉成熟开源的业内小有名气的东东一定比自己写的好),插件demo见系统demo示例。

此模块中的用户为系统的管理人员。

延伸思考

Iframe为子页面,可不受父页面干扰,但是究竟用还是不用好,有待深思的问题;bootstrap-switch boostrap的开关按钮插件并未能初始化开或者关状态,此功能关乎开关的美观,需探究如何修改或选用其它插件待进一步深思。

3)系统待优化之处:

权限访问控制该如何优化(内存?redis?)

Mybatis整合

严格的mvc设计模式

致谢!

初级入门:泽宇、老申、昊总

问题修复:金凤

问题修复:系统参与的全体java同仁

开发者:战神,彭玉,ylz,东龙;

零碎不重要的整理工作(高大上的名字:秘书):本人。

向以上四位开发者致敬!

文档说明

本文档由四位开发者在开发过程中心得记录,由秘书整理汇总而成。最终解释权归四位开发者所有。

参考文献

https://blog.csdn.net/weixin_41981080/article/details/81912941

文末福利:

想要与大家一起交流,可进企鹅群:589847567

群共享文件中有源码下载。

说明:该系统由以上四位开发者在工作之余抽时间分工开发完成,因工作较忙,时间有限等原因,系统中难免有瑕疵不足之处需进一步完善,望大家谅解,在后续版本中我们会不断完善。同时诚邀大才雄心的有志之士加入我们共同开发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/526310.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

幻兽天下修复版java_宠物天下四-幻兽天下

快速搜索机型:诺基亚 N70系列(176208)7610 3230 6600 6260 6620 6630 6670 6680 6681 6682 N70 N72 ;松下: X700 X800 ;联想: P930诺基亚 N73系列(240320)N73 5320 5320XM 5320di_XM 5630XM 5700 5700XM 5710XM 5730XM 6110 6110N 6120 6120C 6120ci 6121 6122C 6124C 6210S 62…

java类spring加载_spring的加载机制?

1,今天面试官问我spring的加载机制有哪些---这么"抽象"的问题作为一个十多年经验的自己写过MVC,IOC,ORM, 等各种中间件小框架的开发人员也回答不出来~确切的说是无从谈起,不知道从哪个角度说这个事情,在我的观点里这个问题本身的问法就有问题,什么叫"加载机制&q…

java计数器策略模式_java设计模式(二十一)--策略模式

对于策略模式,我在很多面试题上看到过考察这一类的问题,这种模式也的确比较好用。 我感觉这种模式就是将不同实现的方法放到一个接口中,然后通过实现这个接口来实现不同的运行结果,这种模式有三部分构成: 策略接口 策略实现类 策略作用类(使用策略的类) 网络上的专业解释:此模式…

java负数十进制转二进制_java中负数的补码转换为十进制

C++全局和静态变量初始化转自:http://www.cnblogs.com/zhenjing/archive/2010/10/15/1852116.html 对于C语言的全局和静态变量,不管是否被初始化,其内存空间都是全局的 ...eclips常用快捷键本文取自:Eclipse中常用快捷键 - yizhang88的专栏 - 博客频道 - CSD…

linux setuid函数_setuid函数解析

在讨论这个setuid函数之前,我们首先要了解的一个东西就是内核为每个进程维护的三个UID值。这三个UID分别是实际用户ID(real uid)、有效用户ID(effective uid)、保存的设置用户ID(saved set-user-ID)。首先说这个实际用户ID,就是我们当前以哪个用户登录了…

java中asl_带你认识绕不开的ASLR

微软从windows vista/windows server 2008(kernel version 6.0)开始采用ASLR技术,主要目的是为了防止缓冲区溢出ASLR技术会使PE文件每次加载到内存的起始地址随机变化,并且进程的栈和堆的起始地址也会随机改变。ASLR(Address space layout randomization…

java复杂性_java – 计算Big-O复杂性

我最终会给这个程序一个类似60,000个400像素图像的输入文件,所以我试着想一想这个代码如何用大输入运行.为了便于阅读,我用“blah”和所有带有简单字母(nn,mm和kk)的ArrayList名称替换了不重要的东西.for (Perceptron P : nn){//blah}for (Perceptron P : mm) {//blah}for (Per…

java泛型与接口_Java泛型用于方法,类和接口

什么是泛型?型就是数据类型参数化。就是说原本定死的数据类型像方法中的形参一样,数据是不确定的,使用的时候由人传进去,泛型就是这样,数据类型不确定了。使用的时候再确定就可以了。泛型的特点是JDK1.5的新特性泛型可…

unix系统编码 java_JAVA字符编码系列三:Java应用中的编码问题

这两天抽时间又总结/整理了一下各种编码的实际编码方式,和在Java应用中的使用情况,在这里记录下来以便日后参考。为了构成一个完整的对文字编码的认识和深入把握,以便处理在Java开发过程中遇到的各种问题,特别是乱码问题&#xff…

Java 捕获 mybatis异常_3 springboot集成mybatis和全局异常捕获

mybatis有两种方式,一种是基于XML,一种是基于注解springboot集成mybatis首先先创建表,这里都简化了DROP TABLE IF EXISTS user;CREATE TABLE user (id int(11) NOT NULL auto_increment,username varchar(255) default NULL,PRIMARY KEY (id)…

java背景图片加上组件_关于 java swing组件加背景图片的问题

最近自己做了一个小的进销存软件,背景图片加上后不能最大化。尝试了好几种方法 最后终于把问题解决了。下面把自己写的实例 分享一下:一个是在JFrame窗体中加如背景图片一个是在Jpanel 面板中加入背景图片都可以伸缩铺满整个屏幕,算是自己的一个小心得。…

java applet 访问文件_使用JavaApplet访问数据库

使用Java Applet访问数据库学习任何的程序语言,当然都得与数据库,Java刚刚诞生的时候,对数据库的支持并不是很好,经过这几年的发展,它对数据库的支持也已经完全达到了成熟的境地。由于这里主要是介绍Java Applet小程序…

java ip 范围内打卡_定位地理位置PHP判断员工打卡签到经纬度是否在打卡之内

具体代码如下所述:/* 计算两组经纬度坐标之间的距离* param $lat1 纬度1* param $lng1 经度1* param $lat2 纬度2* param $lng2 经度2* param int $len_type 返回值类型(1-m 2-km)* param int $decimal 保留小数位数* return float*/public function getDistance($l…

与java线程有关的,线程多少和什么有关?大神们表示有话要说!

原标题:线程多少和什么有关?大神们表示有话要说!来源:importnew.com/10780.htmlEddie的回答:Charlie Martin的回答:benjismith的回答:Neil Coffey的回答:McGovernTheory在StackOverflow提了这样一个问题:Java虚拟机最多支持多少个…

php正则表达式 匹配数字,正则表达式之匹配数字范围

最近有个需求就是根据产品编号批量下架产品,需要下架日期为16-31号之间的产品,比如编号为B201607280023匹配表达式如下:^201607(1[6-9]|2[0-9]|3[0-1]).逻辑很简单,如果是必须是1或2或3开头,如果是1开头则后面范围为6-9&#xff0…

php中带?错误,参考-此错误在PHP中意味着什么?

这是什么?这是有关警告,错误和注意事项的许多答案,这些警告,错误和注意事项在您对PHP进行编程时可能会遇到,并且不知道如何解决它们。这也是一个社区Wiki,因此邀请所有人参与添加并维护此列表。为什么是这样…

yiilite.php,YII Framework学习教程-YII的V-view的render若干函数-2011-11-17 | 学步园

YII中,在action可以通过$this->render来指定它的view。其实还其他一$this->render开头的函数。yiilite.php中有这么几个函数。public function renderText($text,$returnfalse){if(($layoutFile$this->getLayoutFile($this->layout))!false)$text$this-…

php生成链接列表,根据URL链接和抛文本生成链接a标签的PHP函数

这个函数可以为组成一个链接,第一个参数是链接的URL,第二个参数是抛文本。最后生成抛文本function parseurl($url, $text) {if(!$url && preg_match("/((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|ed2k|thunder|synacast){1}:\…

java 项目 人力资源项目,基于jsp的人力资源系统-JavaEE实现人力资源系统 - java项目源码...

基于jspservletpojomysql实现一个javaee/javaweb的人力资源系统, 该项目可用各类java课程设计大作业中, 人力资源系统的系统架构分为前后台两部分, 最终实现在线上进行人力资源系统各项功能,实现了诸如用户管理, 登录注册, 权限管理等功能, 并实现对各类人力资源系统相关的实体…

php阿拉伯语字符串,按字母顺序命名阿拉伯语名称Mysql和php

我试图用阿拉伯语对 alphabetical order 中的结果进行排序,但出于某种原因 not sorting correctly ..$ d1 mysqli_query($ connector,“SELECT * FROM article where type 1ORDER BY name ASC”); while($ a1 mysqli_fetch_array($ d1)){echo“$ a1 [n…