美文网首页
SpringBoot拦截器半自动加载PathPatterns

SpringBoot拦截器半自动加载PathPatterns

作者: 夏天以后灬 | 来源:发表于2019-07-01 19:48 被阅读0次

    1. 序

    SpringBoot中我们会用到拦截器Interceptor,去拦截一些请求,处理相应的业务,如登录验证等,一般我们都是通过手写PathPatterns。

    原代码如下:

     registry.addInterceptor(tokenInterceptor)
                        .addPathPatterns("/**")
                        .excludePathPatterns("/api/hello")
    

    当excludePathPatterns越多的时候代码就不美观,往往在开发的时候会忘记了。
    现提供一种通过注解方式去半自动添加到PathPatterns中。

    2. 实现

    1.自定义注解Permission

    import java.lang.annotation.*;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Permission {
        // 这里可自行修改,添加一些变量
    }
    

    2.控制器方法添加Permission注解

    @RestController
    @RequestMapping("/api")
    public class TestController {
    
        @Permission
        @GetMapping("/hello")
        public String hello() {
            return "hello world!!";
        }
    }
    

    3.配置WebMvcConfigurer

    @Configuration
    public class WebAppConfigurer implements WebMvcConfigurer, ApplicationContextAware {
    
        private static Logger logger = LoggerFactory.getLogger(WebAppConfigurer.class);
    
        // 验证Token拦截器
        @Autowired
        TokenInterceptor tokenInterceptor;
      
       // SpringBoot上下文     
        private ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 通过实现ApplicationContextAware来获取SpringBoot上下文
            this.applicationContext = applicationContext;
        }
    
       // 循环添加到set中 
        private void addExcludePath(Set<String> excludePath, String[] prefixValues, String[] suffixValues) {
            if (suffixValues == null) suffixValues = new String[]{""};
            for (String prefix : prefixValues) {
                for (String suffix : suffixValues) {
                    String path = "/" + prefix;
                    if (suffix.length() != 0) {
                        path += "/" + suffix;
                    }
                    excludePath.add(path.replaceAll("/+", "/"));
                }
            }
        }
    
       // 获取不需要Token验证的path列表
        private List<String> listExcludePath() {
            // 获取有添加RestController的Bean
            Map<String, Object> controllerBeanMap = applicationContext.getBeansWithAnnotation(Controller.class);
            Set<String> excludePath = new HashSet<>();
            try {
                for (Object controller : controllerBeanMap.values()) {
                    Class<?> controllerClass = controller.getClass();
                    RequestMapping controllerMapping = controllerClass.getAnnotation(RequestMapping.class);
                    // 获取url的前缀
                    String[] prefixValues = {""};
                    if (controllerMapping != null) {
                        prefixValues = controllerMapping.value();
                    }
                    // 获取当前类的方法,不含父类方法
                    Method[] controllerMethods = controllerClass.getMethods();
                    for (Method method : controllerMethods) {
                        // 判断是否加了Permission注解
                        Permission permission = method.getAnnotation(Permission.class);
                        if (permission != null) {
                            // 获取所有注解
                            Annotation[] annotations = method.getAnnotations();
                            for (Annotation annotation : annotations) {
                                // 获取RequestMapping、GetMapping...等的value值
                                Class<? extends Annotation> type = annotation.annotationType();
                                if (type.isAnnotationPresent(RequestMapping.class)
                                        || type.isAnnotationPresent(Mapping.class)) {
                    // 反射调用value()方法,获取内容
                                    Method valueMethod = type.getDeclaredMethod("value");
                                    String[] value = (String[]) valueMethod.invoke(annotation);
                                    addExcludePath(excludePath, prefixValues, value);
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
                logger.error("加载permission异常", e);
            }
            return new ArrayList<>(excludePath);
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
    
            if (tokenInterceptor != null) {
                // 获取不需要token的url列表
            List<String> excludePathList = listExcludePath();
    
                registry.addInterceptor(tokenInterceptor)
                        .addPathPatterns("/**")
                        .excludePathPatterns(excludePathList);
            }
    
        }
    
    }
    

    3. 扩展

    这里只是给出一个最简单、常见的逻辑。
    可以根据业务需要对Permission注解添加变量修改,实现符合自己项目的业务逻辑。

    相关文章

      网友评论

          本文标题:SpringBoot拦截器半自动加载PathPatterns

          本文链接:https://www.haomeiwen.com/subject/oxklxctx.html