1.创建一个拦截器,继承HandlerInterceptor
public class AuthorizedInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
可以实现这三个接口(通常只用到第一个)
preHandle(重点)
这个方法在请求处理之前调用(Controller方法调用之前)。它返回一个布尔值,true
表示继续流程(调用下一个拦截器或走完所有要走的拦截器去执行控制器的方法);false
表示流程中断,不会继续调用其他的拦截器(如果有的话),也不会调用目标Controller方法。
postHandle
这个方法在请求处理之后、视图渲染之前调用(Controller方法调用之后)。它主要用于对请求处理之后的模型和视图进行后处理(如果有的话)。如果控制器没有返回任何视图或模型,该方法也可以被调用。
afterCompletion
这个方法在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图执行完毕之后执行。这个方法主要用于进行资源清理工作。
2.写拦截器的逻辑,交给spring管理
@Component
public class AuthorizedInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("拦截器执行了...");
//执行校验token的逻辑,校验成功放行,
// 校验失败则 throw new BusinessException(ResponseEnum.TOKEN_INVALID);
return true;
}
}
3.写一个WebMvcConfig,注册拦截器
package com.gmgx.config;
import com.gmgx.interceptors.AuthorizedInterceptor;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import java.util.List;
@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
//白名单
/*
*:匹配当前路径中的任意单个部分。例如,/webjars/* 会匹配 /webjars/ 下的任意一个具体路径,
比如 /webjars/jquery,但不会匹配 /webjars/jquery/1.0。
**:匹配任意多个路径部分,包括零个或多个子目录。
例如,/webjars/** 可以匹配 /webjars/ 下的任意路径,
比如 /webjars/jquery/1.0、/webjars/jquery,甚至 /webjars/ 本身。
*/
private final List<String> whitelist = List.of(
"/*/login", "/doc.html", "/webjars/**", "/v3/api-docs/**", "/adminApi/validateToken/**"
);
@Resource
private AuthorizedInterceptor authorizedInterceptor;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
//注意这里不适合用创建对象的方式注册拦截器,因为会打破Spring IOC和DI 的特性
//registry.addInterceptor(new AuthorizedInterceptor());
registry.addInterceptor(authorizedInterceptor)//注册拦截器
.addPathPatterns("/**")//注册该拦截器拦截的路径
.excludePathPatterns(whitelist);//排除路径,即不需要被拦截的路径
// registry.addInterceptor(otherInterceptors.....)添加更多拦截器
}
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始设置静态资源映射...");
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
WebMvcConfig继承WebMvcConfigurationSupport,在里面通过addInterceptors方法注册拦截器。
最后要加上@Configuration 注解,交给Spring管理。
循环引用
控制台出现如下信息
# 允许循环引用
spring.main.allow-circular-references=true
或者加上@Lazy注解打断循环引用(最优解)