欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

通过自定义注解排除不需要过滤URL的方法

程序员文章站 2024-03-15 23:43:54
...

一、简介

最近在项目中,使用过滤器的时候,在设置哪些URL需要过滤,哪些URL不需过滤时,一开始想着用配置文件的形式进行配置(当然这种方法也可行),但是我想了想有没有更加优雅的方式,这种URL硬编码在配置文件里面并不太友好,也不好维护,于是我想到了用自定义注解的形式来配置哪些URL进行排除在外,下面就介绍详细的实现步骤。

二、实现步骤

【a】创建springboot项目,pom.xml依赖文件中加入以下依赖:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.reflections</groupId>
            <artifactId>reflections</artifactId>
            <version>0.9.11</version>
            <scope>test</scope>
        </dependency>

【b】编写自定义注解类:排除不需要进行过滤的URL

/**
 * @Description: 自定义注解 - 排除不需要进行过滤的URL
 * @author: weixiaohuai
 * @Date: 2019/10/16 16:54
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface ExcludeDangerousCharacterUrl {
//    String value() default "";
}

【c】创建测试Controller:注意包名

package com.wsh.springboot.testdemo.controller;

import com.wsh.springboot.testdemo.annotation.ExcludeDangerousCharacterUrl;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description:
 * @author: weixiaohuai
 * @Date: 2019/10/16 16:34
 */
@RestController
@RequestMapping("/testController")
public class TestController {

    @RequestMapping("/test1")
    @ExcludeDangerousCharacterUrl
    public String test1() {
        return "test1";
    }

    @RequestMapping("/test2")
    @ExcludeDangerousCharacterUrl
    public String test2() {
        return "test2";
    }

    @RequestMapping("/test3")
    public String test3() {
        return "test3";
    }
}

这里controller的包名为:com.wsh.springboot.testdemo.controller,下面扫描包的时候需要用到,当然如果需要扫描整个项目,那么可以配置项目根目录进行扫描也是可以的。

【d】配置文件application.yml

server:
  port: 1111
spring:
  application:
    name: test-demo
test:
  demo:
    excludeUrlScanPackage: com.wsh.springboot.testdemo.controller

【e】单元测试:

package com.wsh.springboot.testdemo;

import com.wsh.springboot.testdemo.annotation.ExcludeDangerousCharacterUrl;
import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.reflections.Reflections;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestDemoApplicationTests {

    @Value("${test.demo.excludeUrlScanPackage}")
    private String excludeUrlScanPackage;

    @Test
    public void contextLoads() {
        // 需要排除的路径
        List<String> excludeUrls = new ArrayList<>();
        // 设置扫描路径
        Reflections reflections = new Reflections(
                new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage(excludeUrlScanPackage)).setScanners(new MethodAnnotationsScanner()));
        // 扫描指定包内带有@ExcludeDangerousCharacterUrl注解的所有方法集合
        Set<Method> methods = reflections.getMethodsAnnotatedWith(ExcludeDangerousCharacterUrl.class);
        if (null != methods && !methods.isEmpty()) {
            for (Method method : methods) {
                String excludeUrl = method.getAnnotation(RequestMapping.class).value()[0];
                String baseUrl = "";
                String[] valueArr = method.getDeclaringClass().getAnnotation(RequestMapping.class).value();
                if (valueArr.length > 0) {
                    baseUrl = valueArr[0];
                }
                if (StringUtils.isNotBlank(baseUrl)) {
                    excludeUrl = baseUrl + excludeUrl;
                }
                excludeUrls.add(excludeUrl);
            }
        }
        System.out.println("需要排除过滤的URL有:" + StringUtils.join(excludeUrls.toArray(), ","));
    }

}

大体步骤:

  1. 读取配置文件的扫描包路径;
  2. 在指定的包路径下查找所有包含指定注解的类的所有方法集合;
  3. 循环遍历所有方法获取方法上面的RequestMapping注解信息以及对应的值;
  4. 组装需要排除在外的URL;

【f】 测试结果

通过自定义注解排除不需要过滤URL的方法

通过自定义注解排除不需要过滤URL的方法

可见,成功获取了需要进行排除的URL集合,下一步就可以愉快地在过滤器或者其他方法中进行判断了,这种方式是不是比硬编码在配置文件中类似配置白名单的方式好一点,毕竟如果我请求路径改了,那配置文件还不得又改多一次,通过自定义注解就解决了这个问题,也好维护。好了,这就是在java中通过自定义注解排除不需要过滤URL的方法,希望对大家有所帮助。