框架模块说明 #05 权限管理_02

背景

上篇中介绍了权限注册和权限过滤器的使用,这篇我想讲下我对菜单的设计,在面向对象的设计中有一个很重要的观点谁拥有信息谁拥有职责,秉承这个原则,那么谁拥有操作仅限就拥有这个菜单的权限了,在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 "";     // 资源code

    CoreConstant.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 - 全球开发者的开源社区,开源代码托管平台

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值