首页 > 编程知识 正文

前台中台后台管理框架,若依后台管理框架

时间:2023-05-03 19:28:14 阅读:261347 作者:1524

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

本框架采用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 { @Autowired SysEventService 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)@Documentedpublic @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的备份包。

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

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

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

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

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。