拦截器(Interceptor)和过滤器(Filter)都是用于在请求处理过程中进行预处理和后处理的组件,但它们在实现原理、使用场景和功能特点上有显著区别。
拦截器和过滤器的区别
1. 基本概念
过滤器(Filter)
- 基于函数回调的Java Web组件
- 实现了Servlet规范,是Servlet技术的一部分
- 依赖于Servlet容器(如Tomcat)
- 可以对所有进入容器的请求进行处理
拦截器(Interceptor)
- 基于Java反射机制的组件
- 是Spring框架的一部分(Spring MVC中)
- 不依赖Servlet容器,依赖Spring容器
- 主要用于拦截Controller层的请求
2. 执行顺序
scss
客户端请求
↓
Filter1 (前置处理)
↓
Filter2 (前置处理)
↓
DispatcherServlet
↓
Interceptor1 (preHandle)
↓
Interceptor2 (preHandle)
↓
Controller方法执行
↓
Interceptor2 (postHandle)
↓
Interceptor1 (postHandle)
↓
视图渲染
↓
Interceptor2 (afterCompletion)
↓
Interceptor1 (afterCompletion)
↓
Filter2 (后置处理)
↓
Filter1 (后置处理)
↓
返回客户端响应
3. 功能对比
特性 | 过滤器(Filter) | 拦截器(Interceptor) |
---|---|---|
实现原理 | 基于函数回调 | 基于Java反射机制 |
依赖容器 | Servlet容器 | Spring容器 |
触发时机 | 请求进入容器时 | 请求进入Controller前 |
拦截范围 | 所有请求 | DispatcherServlet处理的请求 |
配置方式 | web.xml或注解 | Spring配置或注解 |
访问Servlet API | 可以直接访问 | 通过参数访问 |
4. 代码示例
过滤器示例
java
@Component
@WebFilter(urlPatterns = "/*", filterName = "authFilter")
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 前置处理
String token = httpRequest.getHeader("Authorization");
System.out.println("Filter前置处理: " + httpRequest.getRequestURI());
// 继续执行过滤器链
chain.doFilter(request, response);
// 后置处理
System.out.println("Filter后置处理: " + httpRequest.getRequestURI());
}
}
拦截器示例
java
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 请求处理前执行
System.out.println("Interceptor前置处理: " + request.getRequestURI());
return true; // 返回true继续执行,false中断执行
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
// 请求处理后、视图渲染前执行
System.out.println("Interceptor后置处理: " + request.getRequestURI());
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
// 整个请求完成后执行
System.out.println("Interceptor完成处理: " + request.getRequestURI());
}
}
5. 注册方式
过滤器注册
java
// 方式1:使用@WebFilter注解
@WebFilter(urlPatterns = "/api/*")
public class MyFilter implements Filter { }
// 方式2:在配置类中注册
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter> loggingFilter() {
FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter());
registrationBean.addUrlPatterns("/api/*");
registrationBean.setOrder(1);
return registrationBean;
}
}
拦截器注册
java
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/login");
}
}
6. 使用场景
过滤器适用场景
- 字符编码设置
- 跨域处理
- 请求日志记录
- 权限检查(粗粒度)
- 请求/响应内容压缩
拦截器适用场景
- 登录验证
- 权限检查(细粒度)
- 性能监控
- 事务管理
- 异常处理
7. 性能和开销
- 过滤器:相对轻量,直接在Servlet容器层面处理,开销较小
- 拦截器:需要Spring容器管理,会有一些反射调用开销,但功能更强大
两者可以根据具体需求选择使用,也可以结合使用以发挥各自优势。