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
注解添加变量修改,实现符合自己项目的业务逻辑。
网友评论