亲宝软件园·资讯

展开

springboot通用分支处理权限

zxhtom 人气:0

前言

当引入登录模块后我们需要做菜单。而菜单自然需要权限的参与,我们在springboot中设计的权限细粒度还算是比较细的。当我们查询菜单是需要根据权限查找对应的菜单。但是在springboot中我设计了一个底层超级管理员

 if (SecurityUtils.getSubject().hasRole(RoleList.SUPERADMIN)) {
     listemp = customMapper.selectRootMenusByRoleIdList(null,null, null, null);
 } else {
     listemp = customMapper.selectRootMenusByRoleIdList(roleList, oauthClientId,null, moduleCodes);
 }

这样实现是很正常的思路,通过判断角色是否是超级管理员来做分支执行思路,但是超级管理员可能涉及到多个地方如果在每个地方都这样if else执行的,我觉得有点low, 所以我决定改造一下。不够最终执行的思路依然是if else判断 。 只不过让我们在代码层面上功能间不在那么杂糅在一起

自定义注解

首先我需要两个注解,SuperDirectionSuperDirectionHandler分别表示需要判断超级管理员分支和具体管理员分支的目标函数 。 这句话说的还是有点抽象的,容我慢慢道来!

SuperDirection

 @Target({ElementType.TYPE, ElementType.METHOD})
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 public @interface SuperDirection {
     String value() default StringUtils.EMPTY;
 }

SuperDirectionHandler

 @Target({ElementType.TYPE, ElementType.METHOD})
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 @Component
 public @interface SuperDirectionHandler {
 }

作用

SuperDirection是用于表明该方法需要进行判断超级管理员,而value值存储的就是判断的表达式。关于这个表达式我们后面介绍

SuperDirectionHandler我们不难发现他没有实际属性但是多了一个@Component注解。目的是方便Spring管理该注解;这样我们就可以通过Spring来获取被该注解标注的类了。

位置

该注解释放给全局使用的,在maltcloud结构介绍中我们知道org.framework.core模块是所有模块的基石,所以这两个注解我选择在org.framework.core模块中

切面

 /**定义一个切点; 拦截所有带有SuperDirection注解的类和方法*/
 @Pointcut("@annotation(com.github.zxhtom.core.annotaion.SuperDirection) || @within(com.github.zxhtom.core.annotaion.SuperDirection)")
 public void direction() {
 }
 Map<String, ?> beansOfType = ApplicationContextUtil.getApplicationContext().getBeansOfType(接口class);
 @Around("direction()")
 public Object aroud(ProceedingJoinPoint pjp) throws Throwable {
     Class<?>[] inters = pjp.getTarget().getClass().getInterfaces();
     for (Class<?> inter : inters) {
         Map<String, ?> beansOfType = ApplicationContextUtil.getApplicationContext().getBeansOfType(inter);
         Map<String, Object> beansWithAnnotation = ApplicationContextUtil.getApplicationContext().getBeansWithAnnotation(SuperDirectionHandler.class);
         for (Map.Entry<String, ?> entry : beansOfType.entrySet()) {
             if (beansWithAnnotation.containsKey(entry.getKey())) {
                 try {
                     return doOthersHandler(entry.getValue(), pjp);
                 } catch (Exception e) {
                     log.error("分支执行失败,系统判定执行原有分支....");
                 }
             }
         }
     }
     return pjp.proceed();
 }

条件判断

 MethodSignature msig = (MethodSignature) pjp.getSignature();
 Method targetMethod = value.getClass().getDeclaredMethod(msig.getName(),msig.getParameterTypes());
 SuperDirection superDirection = null;
 superDirection = targetMethod.getAnnotation(SuperDirection.class);
 if (superDirection == null) {
     superDirection = pjp.getTarget().getClass().getAnnotation(SuperDirection.class);
 }
 if(selectAnnotationChoiceDo(superDirection)){
     //如果表达式验证通过,则执行替补bean实现类
     return targetMethod.invoke(value,pjp.getArgs());
 }
 //否则执行原有bean实现类
 return pjp.proceed();

表达式解析

 public interface RootChoiceExpression {
     public boolean haslogined();
     public boolean hasRole(String role);
     public boolean hasAnyRole(String... roles);
 }
 @Service
 public class DefaultChoiceExpression implements RootChoiceExpression {
     @Autowired
     OnlineSecurity onlineSecurity;
     @Override
     public boolean haslogined() {
         return onlineSecurity.getOnlinePrincipal()!=null;
     }
     @Override
     public boolean hasRole(String role) {
         return onlineSecurity.hasAnyRole(role);
     }
     @Override
     public boolean hasAnyRole(String... roles) {
         return onlineSecurity.hasAnyRole(roles);
     }
 }
 private boolean selectAnnotationChoiceDo(SuperDirection superDirection) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
     String value = superDirection.value();
     if (StringUtils.isEmpty(value)) {
         return onlineSecurity.getRoleNames().contains(MaltcloudConstant.SUPERADMIN);
     }
     MethodInfo info = selectInfoFromExpression(value);
     Method declaredMethod = expression.getClass().getDeclaredMethod(info.getMethodName(), String.class);
     Object invoke = declaredMethod.invoke(expression, info.getArgs());
     if (invoke != null && invoke.toString().equals("true")) {
         return true;
     }
     return false;
 }

演示使用

controller

 @RestController
 @RequestMapping(value = "/demo/common")
 public class CommonController {
     @Qualifier(value = "commonTestServiceImpl")
     @Autowired
     CommonTestService commonTestService;
     @RequestMapping(value = "/test",method = RequestMethod.GET)
     public void test() {
         commonTestService.test();
     }
 }

service

 @Service
 @SuperDirectionHandler
 public class CommonTest2ServiceImpl implements CommonTestService {
     @Override
     public void test() {
         System.out.println("hello test 2");
     }
 }
 @Service
 @SuperDirection(value = "")
 public class CommonTestServiceImpl implements CommonTestService {
     @Override
     public void test() {
         System.out.println("hello i am test ing ...");
     }
 }

测试

总结

加载全部内容

相关教程
猜你喜欢
用户评论