拦截器
如果我们要用拦截器,拦截某个接口需要校验,还需要再拦截器方法写上/admin/** 等等,这样代码不可维护,不可扩展
我们可以使用注解来指定这个接口是否要拦截,使用到Spring的InitializingBean,再系统启动的时候通过注解拿到需要拦截的接口路径,代码编写一下
注解编写
@Target(TYPE)
@Retention(RUNTIME)
public @interface Interceptor {
}
接口层编写
@Interceptor
@RestController
@RequestMapping("/admin")
public class AdminController {
}
拦截器编写
public class AdminInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object admin = request.getSession().getAttribute("admin");
// session是空的 直接跳转登录
if (adminLogin == null) {
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
重点
@Configuration
public class InterceptorConfiguration implements WebMvcConfigurer, InitializingBean {
private Set<String> pathPatterns = new HashSet<>();
@Bean
public AdminInterceptor adminInterceptor() {
return new AdminInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 需要拦截的路径
String[] addPathPatterns = new String[pathPatterns.size()];
pathPatterns.toArray(addPathPatterns);
// 循环每个路径添加/**
for (int i = 0; i < addPathPatterns.length; i++) {
addPathPatterns[i] = addPathPatterns[i] + "/**";
}
// 不需要拦截的路径
String[] excludePathPatterns = {"/login"};
// 注册登录拦截器,拦截除excludePathPatterns参数以外的所有请求
registry.addInterceptor(adminInterceptor()).addPathPatterns(addPathPatterns)
.excludePathPatterns(excludePathPatterns);
}
@Override
public void afterPropertiesSet() throws Exception {
// 解析具体路径指定的具体资源、ymal,properties,springboot使用pathMatchingResourcePatternResolver扫描装载到自动注册
PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
// 元数据集缓存读取工厂,用于读取元数据
CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
Resource[] resources = pathMatchingResourcePatternResolver.getResources("classpath*:com/baerwang/controller/*.class");
for (Resource resource : resources) {
// 元数据集缓存工厂读取的数据
MetadataReader reader = cachingMetadataReaderFactory.getMetadataReader(resource);
String className = reader.getClassMetadata().getClassName();
// 获取上下文类加载器
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
Class<?> aClass = contextClassLoader.loadClass(className);
boolean annotationPresent = aClass.isAnnotationPresent(Interceptor.class);
if (annotationPresent) {
RequestMapping annotation = aClass.getAnnotation(RequestMapping.class);
if (annotation != null) {
pathPatterns.addAll(Arrays.asList(annotation.value()));
} else {
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
// 如果接口有get,post,put,delete/mapping等等,需要自行判断添加
RequestMapping field = declaredMethod.getAnnotation(RequestMapping.class);
if (field != null) {
pathPatterns.addAll(Arrays.asList(field.value()));
}
}
}
}
}
}
}