SpringBoot 三种拦截 HTTP 请求方式:Filter,Interceptor 和 AOP。
# 对比
拦截顺序: Filter
-> Interceptor
-> ControllerAdvice
-> @Aspect
-> Controller
方法 | HTTP 请求、响应信息 | 处理请求方法 | 参数 |
---|---|---|---|
过滤器 Filter | √ | × | × |
拦截器 Interceptor | √ | √ | × |
切片 Aspect | √ | √ | √ |
# Filter
实现 Filter 接口
@Slf4j | |
@Component | |
@WebFilter(urlPatterns = {"/**"}, filterName = "tokenAuthorFilter") // 配置拦截规则 | |
public class TokenFilter implements Filter { | |
@Override | |
public void init(FilterConfig filterConfig) throws ServletException { | |
log.info("TokenFilter init {}", filterConfig.getFilterName()); | |
} | |
@Override | |
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { | |
log.info("TokenFilter doFilter 拦截到了请求"); | |
chain.doFilter(request, response); | |
} | |
@Override | |
public void destroy() { | |
log.info("TokenFilter destroy"); | |
} | |
} |
# Interceptor
实现 HandlerInterceptor 接口
@Slf4j | |
@Component | |
public class TokenInterceptor implements HandlerInterceptor { | |
/** | |
* 访问 Controller 某个方法之前这个方法会被调用。 | |
* | |
* @param request | |
* @param response | |
* @param handler | |
* @return false 表示不执行 postHandle 方法,true 表示执行 postHandle 方法 | |
* @throws Exception | |
*/ | |
@Override | |
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { | |
log.info("Token Interceptor preHandle {}", ""); | |
String token = request.getHeader("token"); | |
log.info("Token Interceptor preHandle token :{}", token); | |
log.info("Token Interceptor preHandle uri {}", request.getRequestURL().toString()); | |
if (handler instanceof HandlerMethod) { | |
HandlerMethod handlerMethod = (HandlerMethod) handler; | |
Method method = handlerMethod.getMethod(); | |
log.info("Token Interceptor preHandle getMethod {}", method.getName()); | |
} else if (handler instanceof ResourceHttpRequestHandler) { | |
ResourceHttpRequestHandler resourceHttpRequestHandler = (ResourceHttpRequestHandler) handler; | |
log.info("Token Interceptor preHandle getMethod {}", resourceHttpRequestHandler.getMediaTypes()); | |
} | |
return true; | |
} | |
/** | |
* 请求处理之后、视图渲染之前调用 | |
* preHandle 方法处理之后这个方法会被调用,如果控制器 Controller 出现异常,则不会执行此方法 | |
* | |
* @param request | |
* @param response | |
* @param handler | |
* @param modelAndView | |
* @throws Exception | |
*/ | |
@Override | |
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { | |
log.info("Token Interceptor postHandle"); | |
} | |
/** | |
* 不管是否出现异常,这个 afterCompletion 都会被调用 | |
* | |
* @param request | |
* @param response | |
* @param handler | |
* @param ex | |
* @throws Exception | |
*/ | |
@Override | |
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { | |
log.info("Token Interceptor afterCompletion"); | |
} | |
} |
配置 Spring 容器
/** | |
* TokenInterceptor 自定义拦截器后,需要配置进 Spring | |
* 可以 addCorsMappings 支持跨域 | |
*/ | |
@Slf4j | |
@Configuration | |
public class TokenConfig implements WebMvcConfigurer { | |
@Autowired | |
TokenInterceptor tokenInterceptor; | |
/** | |
* 添加拦截器 | |
* | |
* @param registry | |
*/ | |
@Override | |
public void addInterceptors(InterceptorRegistry registry) { | |
log.info("TokenConfig addInterceptors tokenInterceptor"); | |
registry.addInterceptor(tokenInterceptor) | |
.addPathPatterns("/**") // 加入拦截路径 | |
.excludePathPatterns("/static/**"); // 排除静态资源 | |
} | |
/** | |
* 如果实现 Filter 跨域拦截,这个跨域无效 | |
* 实现拦截器、支持跨域 | |
* | |
* @param registry | |
*/ | |
@Override | |
public void addCorsMappings(CorsRegistry registry) { | |
log.info("TokenConfig addInterceptors addCorsMappings"); | |
registry.addMapping("/**") | |
.allowedOrigins("*") | |
.allowCredentials(true) | |
.allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS", "HEAD") | |
.allowedHeaders("*") | |
.maxAge(3600); | |
} | |
} |
# AOP
pom.xml 添加 AOP 支持
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-aop</artifactId> | |
</dependency> |
@Slf4j | |
@Component // 表示它是一个 Spring 组件 | |
@Aspect // 表示它是一个切面 | |
public class HttpAspect { | |
/** | |
* 通过 ProceedingJoinPoint 对象的 getArgs () 方法获取传进来的参数 | |
* 通过 ProceedingJoinPoint 对象的 proceed () 方法获取返回值的对象 | |
* | |
* @param pjp | |
* @return | |
* 环绕通知 包名。类名。方法名 (参数) | |
*/ | |
@Around("execution(* com.learn.jwttoken.controller.*.*(..))") | |
public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable { | |
log.info("HttpAspect handleControllerMethod filter start"); | |
// 原始 HTTP 请求、响应信息 | |
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | |
HttpServletRequest request = attributes.getRequest(); | |
HttpServletResponse response = attributes.getResponse(); | |
Signature signature = pjp.getSignature(); | |
MethodSignature methodSignature = (MethodSignature) signature; | |
// 获取当前执行的方法 | |
Method targetMethod = methodSignature.getMethod(); | |
log.info("当前执行的方法:{}", targetMethod.getName()); | |
// 获取参数 | |
Object[] objs = pjp.getArgs(); | |
for (Object obj : objs) { | |
log.info("参数:" + obj); | |
} | |
// 获取返回对象 | |
Object object = pjp.proceed(); | |
log.info("获取返回对象 :{}", object); | |
log.info("HttpAspect handleControllerMethod filter end"); | |
// 代理方法的返回值 | |
return pjp.proceed(); | |
} | |
} |