后台管理框架搭建

article/2025/10/1 10:44:43

搭建一套通用的后台管理框架对于以后的快速开发时是非常重要的。通常框架需要包含权限验证、日志、及一些基础数据的增删改查功能。

本框架采用Spring MVC+Mybatis+Freemarker+Adminlte前端 组合在一起搭建一个管理系统。

大概的样子如下:
这里写图片描述

这里写图片描述

这里写图片描述

1.权限

角色->应用->模块->功能
这里写图片描述

数据库专门建立了一张功能表sys_Function,它属于某个模块,它有个权限值字段(该值为2的指数倍,为什么,下面再解释?)。
这里写图片描述

如何判断某个角色是否可以进行某个功能操作(例如删除模块)?
如上图角色权限表sys_RolePermission所示,该表有个字段P_Value等于P_ModuleCode模块所选功能的权限值之和。
例如功能管理模块定义了4个功能,分别为查看、添加、修改、删除功能,这4个功能的权限值分别为1、2、4、8,那么sys_RolePermission的该模块的权限值P_Value如果等于1,则表示只有查看功能,如果等于3,则表示具有查看和添加功能,如果要具有所有功能,则值要等于1+2+4+8=15。

那如果某个用户多个角色对同一个模块有不同的权限值,例如用户x具有角色1和角色2,角色1对模块a的权限值为3,角色2对模块a的权限值为9,那用户对模块a的权限应该是多少呢?其实只要做一个按位与操作即可,即1&9=11,并不是1+9=10.这就是为什么让功能值设置为2的指数倍形式的原因,其实质是为了进行二进制的操作。假如有4个功能,则将权限值用4位的二进制形式表示,每一位分别表示一个功能,0表示无权限,1表示有权限。同理3的二进制形式为0011,9的二进制形式为1001,作与运算后的结果为1011,即权限值为11。
最后判断是否具有某功能,则用该功能权限值与计算后的角色权限值作与运算,例如上面判断是否具有修改功能(权限值为4),将4与11作与运算,4&11=0,则表示无权限,而添加功能(权限值2),2&11=2,则表示有权限,同理删除功能(权限值8),8&11=8表示有权限。

2.日志

写日志功能用到的是AOP切面技术,这样可以与实际的业务代码相分离,互不影响。

<beans:bean id="aspectEventLog" class="com.jykj.check.filter.EventLogAspect" /><!-- <aop:aspectj-autoproxy />  --><!-- 对带有@Operation注解的service包及其子包所有方法执行写日志操作   && execution(* com.jykj.check.service.*.*(..)) --> <aop:config proxy-target-class="true">  <aop:aspect  ref="aspectEventLog">  <aop:pointcut id="myService"  expression="@annotation(com.jykj.check.annotation.Operation) and execution(* com.jykj.check.service..*.*(..)) " />  <aop:after-returning pointcut-ref="myService" method="doAfterReturning"/>  <aop:after-throwing pointcut-ref="myService" method="doAfterThrowing" throwing="ex"/></aop:aspect>  </aop:config>
EventLogAspect.java
package com.jykj.check.filter;import java.lang.reflect.Method;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;import com.alibaba.fastjson.JSON;
import com.jykj.check.annotation.Operation;
import com.jykj.check.exception.AuthorizationException;
import com.jykj.check.service.SysEventService;//事件日志 切面,凡是带有 @Operation 注解的service方法都将会写日志
public class EventLogAspect {@AutowiredSysEventService sysEventService;public void doAfterReturning(JoinPoint jp) throws AuthorizationException {Method soruceMethod = getSourceMethod(jp);if(soruceMethod!=null){Operation oper = soruceMethod.getAnnotation(Operation.class);if (oper != null) {sysEventService.insertEventLog(oper.type(),oper.desc()+"("+extractParam(jp.getArgs(),oper.arguDesc())+") 成功");System.out.println("切面日志:"+oper.desc()+"("+extractParam(jp.getArgs(),oper.arguDesc())+") 成功");}}}public void doAfterThrowing(JoinPoint jp, Throwable ex) throws AuthorizationException {Method soruceMethod = getSourceMethod(jp);if(soruceMethod!=null){Operation oper = soruceMethod.getAnnotation(Operation.class);if (oper != null) {sysEventService.insertEventLog(oper.type(),oper.desc()+"("+extractParam(jp.getArgs(),oper.arguDesc())+" 出现异常:"+ex.getMessage());}}}private Method getSourceMethod(JoinPoint jp){Method proxyMethod = ((MethodSignature) jp.getSignature()).getMethod();try {return jp.getTarget().getClass().getMethod(proxyMethod.getName(), proxyMethod.getParameterTypes());} catch (NoSuchMethodException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();}return null;}private String extractParam(Object[] objParam, String[] arguDesc) {StringBuilder sb = new StringBuilder();int len = objParam.length<arguDesc.length?objParam.length:arguDesc.length;//取最小值for (int i = 0; i < len; i++) {//空字符串将不解析,8个原生数据类型以及字符串直接输出,对象用json输出if(arguDesc[i]!=null && !arguDesc[i].trim().isEmpty()){Object obj = objParam[i];if(obj instanceof String)sb.append(arguDesc[i]+":"+objParam[i]+",");else if(obj instanceof Integer || obj instanceof Byte || obj instanceof Short || obj instanceof Character|| obj instanceof Long || obj instanceof Double || obj instanceof Float || obj instanceof Boolean){sb.append(arguDesc[i]+":"+objParam[i]+",");}else{sb.append(arguDesc[i]+":"+JSON.toJSONString(obj)+",");}}}String rs = sb.toString(); rs = rs.substring(0,rs.length()-1);return rs.length()<=400?rs:rs.substring(0,400);}
}

再需要写日志的方法(通常是service方法)上加一个自定义的注解@Operation即可

package com.jykj.check.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @Descrption该注解描述方法的操作类型和方法的参数意义*/
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
public @interface Operation {/*** @Description描述操作类型   为必填项,1:登录日志2:操作日志*/int type();/*** @Description描述操作意义   比如申报通过或者不通过等*/String desc() default ""; /*** @Description描述操作方法的参数意义 数组长度需与参数长度一致,否则会参数与描述不一致的情况*/String[] arguDesc() default {};
}

3.前端框架

前端框架使用的是AdminLTE,其包含了很多技术例如bootstrap、datatables等等,非常繁杂。
可以从官网下载该框架:AdminLTE官网

4.其他

框架涉及到的东西实在是太多太多,这里就不一 一列举了。
开发环境:
Spring tool suite 3.9+JDK8+Sqlserver2008
Import项目后如果发现一大堆错误,通常是pom.xml文件中所依赖的jar包未下载,需要手动或在线下载jar包到你本地的mven仓库中。
下面附上框架项目的下载地址,里面包含项目以及Sqlserver的数据库Check的备份包。

框架项目下载地址:框架项目下载

《道德经》第三章:
不上贤,使民不争;不贵难得之货,使民不为盗;不见可欲,使民不乱。是以圣人之治也,虚其心,实其腹,弱其志,强其骨,恒使民无知、无欲也。使夫知不敢、弗为而已,则无不治矣。

译文:不推崇有才德的人,导使老百姓不互相争夺;不珍爱难得的财物,导使老百姓不去偷窃;不显耀足以引起贪心的事物,导使民心不被迷乱。因此,圣人的治理原则是:排空百姓的心机,填饱百姓的肚腹,减弱百姓的竞争意图,增强百姓的筋骨体魄,经常使老百姓没有智巧,没有欲望。致使那些有才智的人也不敢妄为造事。圣人按照“无为”的原则去做,办事顺应自然,那么,天才就不会不太平了。

无为并非啥事都不做,无为是执政者不为自己去攫取民众的利益。


http://chatgpt.dhexx.cn/article/8kd9ImBu.shtml

相关文章

flutter 后台管理框架

一直希望有一个简单实用&#xff0c;强大的后台管理框架&#xff0c;能快速定义各个管理页面 只注重业务上面的处理&#xff0c;经过良久的寻找 终于找了一款符合大众的开源flutter 框架 运行 example 中lib目录下的 main 编译环境 flutter3 vscode config文件夹下面配置 业务…

一定要收藏的5个后台管理系统的前端框架

当你开发新项目的时候&#xff0c;如何快速的完成一个项目的搭建&#xff0c;这个时候就需要借助到一些模板了&#xff0c;现在网上各类UI模板都是相当的齐全的&#xff0c;本文就介绍几个靓仔觉得非常不错的前端框架&#xff0c;感兴趣的可以了解一下。 1、vue-element-admin …

14个适合后台管理系统快速开发的前端框架

1、D2admin 开源地址&#xff1a;https://github.com/d2-projects/d2-admin 文档地址&#xff1a;https://d2.pub/zh/doc/d2-admin/ 效果预览&#xff1a;https://d2.pub/d2-admin/preview/#/index 开源协议&#xff1a;MIT License 2、vue-element-admin 开源地址&#x…

QT的信号与槽原理(经典)

QT的信号与槽原理&#xff08;经典) 信号与 槽作为 QT的核心机制在 QT编程中有着广泛的应用&#xff0c;本文介绍了信号与 槽的一些基本概念、元对象工具以及在实际使用过程中应注意的一些问题。 QT是一个跨平台的C GUI应用构架&#xff0c;它提供了丰富的窗口部件集&#xf…

qt之信号与槽的原理

只要问到qt的亮点是什么&#xff0c;不得不说就是信号与槽机制。信号与槽类似观察者模式。 在面向对象的编程中&#xff0c;都会创建很多实例&#xff0c;而每个实例都是独立的&#xff0c;要想每个实例能够协同合作&#xff0c;那么就会需要一种对象间传递消息的机制&#xf…

[Qt]信号和槽机制

信号和槽机制 目录 信号和槽机制 前言&#xff1a; 1.系统自带的信号和槽 代码实现&#xff1a; 如何查找系统自带的信号和槽(如何使用帮助文档) 2.自定义信号和槽 (1)创建Teacher类和Student类 (2)自定义信号&#xff1a; (3)自定义槽函数&#xff1a; (4)自定义信…

Qt信号与槽机制原理及优缺点

信号和插槽用于对象之间的通信。信号和槽机制是Qt的核心特性&#xff0c;可能也是与其他框架提供的特性最大不同的部分。Qt的元对象系统使信号和插槽成为可能。 作为一个C/C程序员来说 回调应该属于深入人心的机制了。其他工具包使用回调来实现这种通信。回调函数是一个指向函…

QT多线程下的信号与槽机制

目录 1、QThread类 2、创建并启动线程 3、多线程信号与槽 4、信号与槽的调用线程&#xff1f; 5、调整信号与槽所在线程的依附关系 6、信号与槽的连接方式 QT 中 QObject 作QT中类的最终父类&#xff0c;具有自定义信号与槽的能力&#xff0c;只要继承自这个类的类&#xf…

QT—信号与槽详解

目录 一、什么是信号与槽 二、信号与槽的添加 1.添加槽方法 2.添加信号 3.发送信号 4.信号与槽连接 三、连接类型 1.一对一 2.一对多 3.多对一 四、信号与槽断开连接 1.断开一个对象的所有信号关联 2.断开指定信号的所有关联 3.断开指定接收者的所有关联 4.断…

Qt的信号与槽

引入 在GUI编程中&#xff0c;组件组件如何实现通信是核心的技术内容。 Qt使用了信号与槽的机制&#xff0c;为此Qt引入了一些关键字slots、signals、emit&#xff0c;这些都是Qt特有的关键字&#xff0c;然后这些关键字会被Qt的moc转换位标准的C语句。 Qt 的部件类中有一些已…

Linux下的QT信号和槽机制(二)

目录 1.基本知识点 2.信号机制 3.槽机制 4.元对象工具 5.信号和槽机制原理 &#xff08;1&#xff09;信号和槽机制 &#xff08;2&#xff09;信号和槽函数的关联 &#xff08;3&#xff09;信号和槽的断开 &#xff08;4&#xff09;信号和槽的优点 &#xff08;5&…

Qt信号与槽原理

Qt信号与槽原理 本文为原创文章&#xff0c;转载请注明出处&#xff0c;或注明转载自“黄邦勇帅(原名&#xff1a;黄勇) 本文出自本人原创著作《Qt5.10 GUI完全参考手册》网盘地址&#xff1a; https://pan.baidu.com/s/1iqagt4SEC8PUYx6t3ku39Q 《C语法详解》网盘地址&#…

Qt 之 信号槽机制及优缺点

1. Qt 信号槽机制 概念&#xff1a; 信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽&#xff0c;实际就是观察者模式。当某个事件发生之后&#xff0c;比如&#xff0c;按钮检测到自己被点击了一下&#xff0c;它就会发出一个信号&#xff08;signal&#xff09;。这种发出是…

【Qt】一篇全面的信号和槽函数机制总结

信号和槽函数机制 文章目录 信号和槽函数机制一、信号和槽机制简介二、【信号】&#xff08;2-1&#xff09;信号的发出&#xff08;2-2&#xff09;信号的处理 三、【槽函数】&#xff08;3-1&#xff09;带有默认参数的信号和槽函数&#xff08;3-2&#xff09;使用QObject::…

Qt: 信号与槽机制

一、信号和槽机制是什么&#xff1f; 1 Qt信号槽机制&#xff1a;是Qt的核心机制&#xff0c;它是Qt定义的一种对象间的通讯机制&#xff0c;且独立于标准C/C语言。 2 信号&#xff08;signals&#xff09;:当某个类对象发生内部改变时&#xff0c;发射“信号”随后与关联的“槽…

Qt 信号和槽的机制(逻辑清晰的来说清楚信号和槽,呕心沥血之作)

Qt 信号和槽的机制 首先说声对不起&#xff0c;上次在PyQt5中写信号与槽&#xff0c;由于时间原因没有写完。有小伙伴留言说&#xff0c;希望把这章补全。所以&#xff0c;这是一篇迟来的文章&#xff0c;再次向大家说声抱歉。 一、桌面程序的结构 Qt的使用场景&#xff0c;…

Qt信号和槽机制emit的使用

1.相关概念&#xff1a; [1].信号&#xff08;Signal&#xff09;就是在特定情况下被发射的事件 [2].槽&#xff08;Slot&#xff09;就是对信号响应的函数。槽就是一个函数 [3].信号与槽之间的关联&#xff1a;是用 QObject::connect() 函数实现的&#xff0c;其基本格式是…

Qt信号和槽机制详解

Qt信号和槽机制详解 信号和槽是 Qt 特有的消息传输机制&#xff0c;它能将相互独立的控件关联起来。 举个简单的例子&#xff0c;按钮和窗口本是两个独立的控件&#xff0c;点击按钮并不会对窗口造成任何影响。通过信号和槽机制&#xff0c;我们可以将按钮和窗口关联起来&…

Qt信号与槽机制

一. 简介 就我个人来理解&#xff0c;信号槽机制与Windows下消息机制类似&#xff0c;消息机制是基于回调函数&#xff0c;Qt中用信号与槽来代替函数指针&#xff0c;使程序更安全简洁。 信号和槽机制是 Qt 的核心机制&#xff0c;可以让编程人员将互不相关的对象绑定在一起&…

Qt --- 信号与槽

信号与槽概述 信号与槽是 Qt 框架引以为豪的机制之一。所谓信号与槽&#xff0c;实际就是观察者模式(发布-订阅模式)。当某个事件发生之后&#xff0c;比如&#xff0c;按钮检测到自己被点击了一下&#xff0c;它就会发出一个信号&#xff08;signal&#xff09;。这种发出是没…