背景
上篇中介绍了权限注册和权限过滤器的使用,这篇我想讲下我对菜单的设计,在面向对象的设计中有一个很重要的观点谁拥有信息谁拥有职责,秉承这个原则,那么谁拥有操作仅限就拥有这个菜单的权限了,在Vue做为后台管理大行其道的今天,应该是叫router比较合适。
注解设计
所以我在设计SystemResource这个注解时就设计了,menuCode/menuName/parentMenuCode/parentMenuName这四个feild来标注菜单,其中parentMenuCode/parentMenuName用来标注在类上的,menuCode/menuName标注在方法上。
package org.cloud.dimension.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;
import org.cloud.constant.CoreConstant;
import org.springframework.stereotype.Component;/*** 系统资源注解*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface SystemResource {String path() default ""; //资源路径,用于分类资源,例如 商品管理/SPU管理String description() default ""; // 资源名称String value() default ""; // 资源codeCoreConstant.AuthMethod authMethod() default CoreConstant.AuthMethod.ALLSYSTEMUSER; //验证方式,默认为所有的登录用户,ByUserAuth// 如下为菜单相关String menuName() default ""; // 菜单名称,可选,如果不为空,那么会自动创建菜单String menuCode() default ""; // 菜单编码,可选,如果不为空,那么会自动创建菜单String parentMenuCode() default ""; // 父级菜单名称,默认为无上级,用controller的类上String parentMenuName() default ""; // 父级菜单名称,默认为无上级,用controller的类上int index() default 0; // 序号String icon() default "";
}
资源和菜单同步
在上篇中提到同步资源的时候,首先会同步父级菜单到menu表里
private ParentMenuCreate getParentMenuCreate(Map<String, Object> beans, String beanName) {SystemResource beanResourceAnnotation = AnnotationUtils.findAnnotation(beans.get(beanName).getClass(), SystemResource.class);logger.info("beanResourceAnnotation:{}", beanResourceAnnotation);TFrameMenu parentMenu = null;if (beanResourceAnnotation == null) {return null;}if (!SystemStringUtil.single().isEmpty(beanResourceAnnotation.parentMenuCode())) {parentMenu = new TFrameMenu();parentMenu.setMenuCode(beanResourceAnnotation.parentMenuCode());parentMenu.setMenuName(beanResourceAnnotation.parentMenuName());parentMenu.setSeqNo(beanResourceAnnotation.index());parentMenu.setCreateBy("admin");parentMenu.setCreateDate(new Date());parentMenu.setUpdateBy("admin");parentMenu.setUpdateDate(new Date());parentMenu.setType(0); // 类上注解定义为目录parentMenu.setShowType(0);parentMenu.setIcon(StrUtil.isEmpty(beanResourceAnnotation.icon())? "iconfont icon-caidan" : beanResourceAnnotation.icon());parentMenu.setComponentPath("layout/routerView/parent"); //新的后台管理parentMenu.setMenuUrl(beanResourceAnnotation.path());parentMenu.setStatus(1);try {String jsonStr = JSON.toJSONString(systemResourceRegisterFeignClient.saveOrUpdateMenu(parentMenu).getData());parentMenu = JSON.parseObject(jsonStr, TFrameMenu.class);logger.info("parentMenu:{}", parentMenu);} catch (Exception e) {logger.error(e.getMessage(), e);}}return new ParentMenuCreate(beanResourceAnnotation, parentMenu);}
然后会将方法上的menuCode注解挂在定义的父菜单下,并将菜单和资源的关系绑定在一起
TFrameMenu menu = new TFrameMenu();menu.setMenuCode(methodResourceAnnotation.menuCode());menu.setMenuName(methodResourceAnnotation.menuName());menu.setSeqNo(methodResourceAnnotation.index());menu.setCreateBy("admin");menu.setParentMenuId(parentMenuResult.parentMenu.getMenuId());menu.setIcon(StrUtil.isEmpty(methodResourceAnnotation.icon()) ? "iconfont icon-biaodan" : methodResourceAnnotation.icon());menu.setType(1);menu.setMenuUrl(StrUtil.addPrefixIfNot(methodResourceAnnotation.menuCode(),"/")); // 新版本的后台管理,加上/menu.setComponentPath(methodResourceAnnotation.menuCode() + "/index");menu.setCreateDate(new Date());menu.setUpdateBy("admin");menu.setUpdateDate(new Date());menu.setStatus(1);if (AuthMethod.BYUSERPERMISSION.equals(methodResourceAnnotation.authMethod())) {menu.setShowType(1);String functionResourceCode = String.format("%s::%s::%s", microName, parentMenuResult.beanResourceAnnotation.path(),methodResourceAnnotation.value());menu.setFunctionResourceCode(functionResourceCode);} else {menu.setShowType(0);}try {logger.info("menu:{}", systemResourceRegisterFeignClient.saveOrUpdateMenu(menu));} catch (Exception e) {logger.error(e.getMessage(), e);}
菜单同步后,前台根据同步的代码路径开发相应的页面就好了。
总结
通过这篇文章,其实已经基本讲清楚的操作权限相关的内容,下面会讲操作权限的相关内容,敬请期待。详细代码请参考
GitCode - 全球开发者的开源社区,开源代码托管平台