使用spring事件驱动机制,实现权限信息的自动收集存库

本文介绍了一种利用Spring事件驱动机制及自定义注解自动提取系统中所有Controller URL及其权限信息的方法,以替代人工配置。
    最近在做权限管理,希望能够在容器初始化后,自动的将所有Controller上的url进行收集,并存放到权限表中,从而代替人工配置的方式。实现思路如下:


    spring事件驱动机制+注解来实现。


    spring事件驱动机制


    spring在容器初始化之后,会触发ContextRefreshedEvent等事件,只要实现了ApplicationListener就可以捕获这个事件,这个时候,我们就可以做很多事情了,比如权限信息的提取,加载缓存等等,所以,我们的思路也是基于此的。


    1、自定义注解


    [java] view plain copy


    import java.lang.annotation.ElementType;


    import java.lang.annotation.Retention;


    import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;


    /**


    * 权限注解,后台会在容器中所有的类都加载完毕之后,通过扫描该注解,将系统中所有url对应的权限信息存到数据库中,* 减少人为配置


    * 注意:之所以加该注解而不直接用RequestMapping原因如下:


    * 1、经测试,classpath下其他的框架中也可能存在使用RequestMapping的情况,这样就会出错,例如org.springframework.boot.autoconfigure.web.BasicErrorController类* 2、RequestMapping没有其他的需要的信息,用起来也不灵活* @author chhliu


    *


    */


    @Retention(RetentionPolicy.RUNTIME)


    @Target({ElementType.METHOD, ElementType.TYPE})public @interface PermissionPath {


    // 权限路径,需要和RequestMapping里面的路径一致public String path() default "";


    // 当前Controller对应的模块名称


    public String moduleName() default "";


    // 当前Url对应的操作


    public Operation operation();


    }


    [java] view plain copy


    /**


    * controller中url对应的操作权限,目前限定的操作为4种* @author chhliu


    */


    public enum Operation {


    VIEW, UPDATE, ADD, DELETE


    }


    2、实现ApplicationListener


    [java] view plain copy


    import java.lang.reflect.Method;


    import java.util.Map;


    import java.util.Map.Entry;


    import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationListener;import org.springframework.context.event.ContextRefreshedEvent;import org.springframework.core.annotation.AnnotationUtils;import org.springframework.stereotype.Component;import com.chhliu.srd.rdcloud.annotation.PermissionPath;/**


    * spring的事件驱动机制


    * 实现ApplicationListener后,容器会在初始化所有的bean之后,触发refresh事件* 所以在该方法中,可以实现对系统中所有Controller中url的提取* @author chhliu


    *


    */


    @Component


    public class ExtractPermissionInformationContext implements ApplicationListener<ContextRefreshedEvent> {/**


    * refresh事件


    */


    @Override


    public void onApplicationEvent(ContextRefreshedEvent event) {System.out.println("===============开始提取权限信息================");System.out.println(event.getTimestamp());// 通过event获取到spring 的ApplicationContext上下文ApplicationContext applicationContext = event.getApplicationContext();// 获取到所有Bean上标记有RequestMapping注解的BeanMap<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(PermissionPath.class);// 判空


    if(null != beansWithAnnotation && !beansWithAnnotation.isEmpty()){for(Entry<String, Object> entry:beansWithAnnotation.entrySet()){// 获取带指定注解的类


    Class<? extends Object> clz = entry.getValue().getClass();System.out.println("className:"+clz.getName());// 通过类获取到类上注解的信息


    PermissionPath rm = AnnotationUtils.findAnnotation(clz, PermissionPath.class);System.out.println("class requestMapping:"+rm.path());// 获取该类下的所有方法


    Method[] methods = clz.getMethods();


    for(Method m:methods){


    // 如果该方法上标记了对应的注解,则是我们需要提取权限信息的方法if(m.isAnnotationPresent(PermissionPath.class)){// 获取方法上注解的信息


    PermissionPath ma = m.getAnnotation(PermissionPath.class);System.out.println("method requestMapping:"+ma.path());}


    }


    }


    }


    System.out.println("===============开始提取权限信息================");System.out.println(event.getTimestamp());}


    }


    测试结果如下:


    [java] view plain copy


    ===============开始提取权限信息================1503631242290


    className:com.chhliu.srd.rdcloud.contractmanager.contractimport.controller.ContractImportControllerclass requestMapping:/api/contractimport


    method requestMapping:updateMilston


    method requestMapping:queryDepartMent


    method requestMapping:queryByCondition


    method requestMapping:/fileUpload


    通过上面的几个步骤,就基本实现了对权限信息的自动提取工作。那我们更近一步,spring的事件驱动机制是怎么工作的了,下面我们来看一个简单的示例。


    spring事件驱动流程:spring的事件传播机制 是基于观察者模式(Observer)实现的,它可以将 Spring Bean 的改变定义为事件 ApplicationEvent,通过 ApplicationListener 监听 ApplicationEvent 事件,一旦Spring Bean 使用 ApplicationContext.publishEvent( ApplicationEvent event )发布事件后,Spring 容器会通知注册在容器中的所有 ApplicationListener 接口的实现类,最后 ApplicationListener 接口实现类判断是否响应刚发布出来的 ApplicationEvent 事件。


    从上面的流程原理这段描述中,我们可以发现几个关键类:1、ApplicationEvent,2、ApplicationListener所以,在使用中,会有如下几个步骤:


    1、建立事件类,即我们对外要发布的事件


    2、建立监听类,监听第一步中发布的事件


    3、发布事件


    下面我们就通过一个简单的示例来逐步实现,示例需求:用户在注册成功之后,发布通知事件,通知采取短信和邮件两种通知方式,当事件监听器监听到发布的事件之后,通知用户注册成功。


  宁波隆鼻医院 http://www.iyestar.com/bbzx/



    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值