背景
Servlet的过滤器(Filter)和Spring MVC的拦截器(Interceptor)都是用于在请求处理过程中对请求进行拦截和处理的组件。它们之间的主要区别在于它们的作用范围和使用方式。
作用范围
Filter:过滤器是基于Servlet规范的,它可以在整个Web应用程序中对所有请求进行拦截和处理。过滤器可以用于处理诸如身份验证、日志记录、数据压缩等通用任务。
Interceptor:拦截器是Spring MVC框架特有的,它只能在Spring MVC的控制器(Controller)层对请求进行拦截和处理。拦截器通常用于处理诸如权限验证、日志记录、数据绑定等与业务逻辑相关的任务。
使用方式
Filter:过滤器是基于Java Servlet规范的,需要在web.xml文件中进行配置。过滤器会在请求到达Servlet之前进行处理,也可以在响应返回给客户端之前进行处理。
Interceptor:拦截器是Spring MVC框架提供的,需要在Spring MVC配置文件中进行配置。拦截器会在请求到达控制器之前进行处理,也可以在响应返回给客户端之前进行处理。
Web请求的执行流程
案例实践
过滤器 - Filter接口
java
/**
* Filter:过滤器是基于Java Servlet规范的,需要在web.xml文件中进行配置。
* 过滤器会在请求到达Servlet之前进行处理,也可以在响应返回给客户端之前进行处理。
*/
@Component
@Order(1)
public class TokenValidateFilter implements Filter {
private static Logger logger = LoggerFactory.getLogger(TokenValidateFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
logger.info("TokenValidateFilter doFilter...");
if (request.getParameter("token") != null) {
chain.doFilter(request, response);
} else {
logger.info("TokenValidateFilter doFilter fail, request with no token..");
}
// 在响应返回给客户端之前执行的操作,比如设置响应的Locale
response.setLocale(Locale.CANADA);
logger.info("TokenValidateFilter doFilter finish, 响应即将返回给客户端,这里可以对响应进行修改");
}
}
-
过滤器会简单判断是否包含token参数
-
成功:继续请求下一步处理
-
失败:打印日志,结束响应
-
拦截器 - HandlerInterceptor接口
java
/**
* Interceptor:拦截器是Spring MVC框架提供的,需要在Spring MVC配置文件中进行配置。
* 拦截器会在请求到达控制器之前进行处理,也可以在响应返回给客户端之前进行处理。
*/
public class RequestInterceptor implements HandlerInterceptor {
private static Logger log = LoggerFactory.getLogger(TokenValidateFilter.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("RequestInterceptor preHandle.. url = {}", request.getRequestURI());
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("RequestInterceptor postHandle.. url = {}", request.getRequestURI());
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("RequestInterceptor afterCompletion.. url = {}", request.getRequestURI());
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
MVC配置类 - WebMvcConfigurer
java
@Slf4j
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
log.info("WebConfig add interceptor...");
registry.addInterceptor(new RequestInterceptor()).addPathPatterns("/**");
}
}
Filter鉴权失败
日志
css
2024-08-28 20:10:25.214 INFO [users,68f83a568240f784,68f83a568240f784,true] 19915 --- [nio-8891-exec-9] c.b.config.filter.TokenValidateFilter : TokenValidateFilter doFilter...
2024-08-28 20:10:27.813 INFO [users,68f83a568240f784,68f83a568240f784,true] 19915 --- [nio-8891-exec-9] c.b.config.filter.TokenValidateFilter : TokenValidateFilter doFilter fail, request with no token..
2024-08-28 20:10:27.814 INFO [users,68f83a568240f784,68f83a568240f784,true] 19915 --- [nio-8891-exec-9] c.b.config.filter.TokenValidateFilter : TokenValidateFilter doFilter finish, 响应即将返回给客户端,这里可以对响应进行修改
验证
如果Filter责任链执行中断并return,就没有后面Interceptor啥事了,更没有Controller的执行机会了。
Filter鉴权成功
继续执行Controller和Interceptor的逻辑,并正常返回。
日志
go
2024-08-28 19:23:58.846 INFO [users,97dac7b87b9435c6,97dac7b87b9435c6,true] 19915 --- [nio-8891-exec-7] c.b.config.filter.TokenValidateFilter : TokenValidateFilter doFilter...
2024-08-28 19:24:00.841 DEBUG [users,97dac7b87b9435c6,97dac7b87b9435c6,true] 19915 --- [nio-8891-exec-7] o.s.web.servlet.DispatcherServlet : GET "/user_select?id=1&token=11", parameters={masked}
2024-08-28 19:24:00.842 INFO [users,97dac7b87b9435c6,97dac7b87b9435c6,true] 19915 --- [nio-8891-exec-7] c.b.config.filter.TokenValidateFilter : RequestInterceptor preHandle.. url = /user_select
2024-08-28 19:24:12.132 INFO [users,97dac7b87b9435c6,97dac7b87b9435c6,true] 19915 --- [nio-8891-exec-7] c.b.config.filter.TokenValidateFilter : RequestInterceptor postHandle.. url = /user_select
2024-08-28 19:24:24.648 INFO [users,97dac7b87b9435c6,97dac7b87b9435c6,true] 19915 --- [nio-8891-exec-7] c.b.config.filter.TokenValidateFilter : RequestInterceptor afterCompletion.. url = /user_select
2024-08-28 20:08:17.931 WARN [users,,,] 19915 --- [ini housekeeper] com.zaxxer.hikari.pool.HikariPool : mac_mini - Thread starvation or clock leap detected (housekeeper delta=43m53s281ms).
2024-08-28 20:08:17.931 INFO [users,,,] 19915 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration
2024-08-28 20:08:17.935 DEBUG [users,97dac7b87b9435c6,97dac7b87b9435c6,true] 19915 --- [nio-8891-exec-7] o.s.web.servlet.DispatcherServlet : Completed 200 OK
2024-08-28 20:08:17.936 INFO [users,97dac7b87b9435c6,97dac7b87b9435c6,true] 19915 --- [nio-8891-exec-7] c.b.config.filter.TokenValidateFilter : TokenValidateFilter doFilter finish, 响应即将返回给客户端,这里可以对响应进行修改