过滤器Filter和拦截器HandlerIntercepter的区别及用法

发布时间:2021-06-23 09:30:06 作者:chen
来源:亿速云 阅读:659
# 过滤器Filter和拦截器HandlerIntercepter的区别及用法

## 目录
1. [概述](#概述)
2. [核心概念解析](#核心概念解析)
   - [2.1 过滤器(Filter)](#21-过滤器filter)
   - [2.2 拦截器(HandlerInterceptor)](#22-拦截器handlerinterceptor)
3. [工作原理对比](#工作原理对比)
   - [3.1 执行时机](#31-执行时机)
   - [3.2 作用范围](#32-作用范围)
   - [3.3 实现机制](#33-实现机制)
4. [代码实现详解](#代码实现详解)
   - [4.1 Filter实现示例](#41-filter实现示例)
   - [4.2 Interceptor实现示例](#42-interceptor实现示例)
5. [应用场景分析](#应用场景分析)
   - [5.1 Filter适用场景](#51-filter适用场景)
   - [5.2 Interceptor适用场景](#52-interceptor适用场景)
6. [Spring中的整合使用](#spring中的整合使用)
7. [性能对比与注意事项](#性能对比与注意事项)
8. [常见问题解答](#常见问题解答)
9. [总结](#总结)

## 概述

在Java Web开发中,过滤器和拦截器是两种重要的请求处理机制,它们都能对HTTP请求进行预处理和后处理,但在实现原理和应用场景上存在本质区别。本文将深入分析两者的技术差异,并通过实际代码示例展示它们的典型用法。

## 核心概念解析

### 2.1 过滤器(Filter)

**定义**:Filter是Servlet规范定义的组件,基于函数回调实现,作用于Web容器层面。

**核心特性**:
- 属于J2EE标准组件
- 在请求进入Servlet容器后、到达Servlet之前执行
- 可以修改请求/响应对象(装饰器模式)
- 配置在web.xml或通过@WebFilter注解

**生命周期**:
```java
init(FilterConfig) → doFilter(ServletRequest, ServletResponse, FilterChain) → destroy()

2.2 拦截器(HandlerInterceptor)

定义:Interceptor是Spring MVC框架提供的机制,基于AOP思想实现,作用于DispatcherServlet之后。

核心特性: - Spring框架特有组件 - 可以访问HandlerMethod上下文 - 支持更精细的拦截控制(如基于路径模式) - 通过实现接口并注册到InterceptorRegistry

方法组成

preHandle() → postHandle() → afterCompletion()

工作原理对比

3.1 执行时机

阶段 Filter Interceptor
容器初始化 ×
进入DispatcherServlet前 ×
Controller方法调用前 ×
视图渲染前 ×
请求完成时

典型调用链:

HTTP请求 → 容器 → FilterChain → DispatcherServlet → Interceptor → Controller

3.2 作用范围

Filter: - 对所有请求生效(包括静态资源) - 可以修改请求/响应内容 - 无法获取Spring上下文信息

Interceptor: - 仅对Controller请求生效 - 可以访问HandlerMethod参数 - 能与Spring其他组件(如Service)交互

3.3 实现机制

Filter 采用责任链模式:

public void doFilter(ServletRequest request, ServletResponse response, 
    FilterChain chain) {
    // 前置处理
    chain.doFilter(wrappedRequest, wrappedResponse); 
    // 后置处理
}

Interceptor 基于拦截器栈:

boolean preHandle(...) {
    // 返回true继续执行后续拦截器
}
void postHandle(...) {
    // 视图渲染前处理
}

代码实现详解

4.1 Filter实现示例

日志过滤器

@WebFilter("/*")
public class LogFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, 
            FilterChain chain) throws IOException, ServletException {
        
        long start = System.currentTimeMillis();
        HttpServletRequest request = (HttpServletRequest) req;
        
        // 记录请求信息
        System.out.printf("Request URI: %s%n", request.getRequestURI());
        
        chain.doFilter(req, res);  // 关键调用
        
        // 记录响应时间
        System.out.printf("Request %s completed in %dms%n", 
            request.getRequestURI(),
            System.currentTimeMillis() - start);
    }
}

注册方式: 1. 注解方式:@WebFilter(urlPatterns = "/*") 2. XML配置:

<filter>
    <filter-name>logFilter</filter-name>
    <filter-class>com.example.LogFilter</filter-class>
</filter>

4.2 Interceptor实现示例

权限拦截器

public class AuthInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
            HttpServletResponse response, Object handler) throws Exception {
        
        if (!checkAuth(request)) {
            response.sendError(403, "Forbidden");
            return false;  // 中断请求
        }
        return true;
    }
    
    @Override
    public void postHandle(HttpServletRequest request, 
            HttpServletResponse response, Object handler, 
            ModelAndView modelAndView) {
        // 可添加全局模型数据
        modelAndView.addObject("version", "1.0.0");
    }
}

注册配置

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/public/**");
    }
}

应用场景分析

5.1 Filter适用场景

  1. 跨域处理
response.setHeader("Access-Control-Allow-Origin", "*");
  1. 请求/响应包装
chain.doFilter(new XSSRequestWrapper(request), response);
  1. 全局编码设置
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
  1. 敏感词过滤
String content = request.getParameter("content");
content = SensitiveWordFilter.replace(content);

5.2 Interceptor适用场景

  1. 权限验证
if (request.getSession().getAttribute("user") == null) {
    response.sendRedirect("/login");
    return false;
}
  1. 接口耗时统计
long start = System.currentTimeMillis();
request.setAttribute("startTime", start);
  1. 参数预处理
String token = request.getHeader("X-Token");
TokenUtils.verify(token);
  1. 日志记录
log.info("{} {} from {}", 
    request.getMethod(), 
    request.getRequestURI(),
    request.getRemoteAddr());

Spring中的整合使用

组合应用示例

请求 → EncodingFilter → SecurityFilter → DispatcherServlet → 
      LogInterceptor → AuthInterceptor → Controller

执行顺序控制: 1. Filter顺序:通过@Order注解或web.xml中<filter-mapping>顺序 2. Interceptor顺序:注册时的添加顺序

注意事项: - 避免在Filter和Interceptor中重复处理相同逻辑 - Filter中抛出的异常不会被@ControllerAdvice捕获 - Interceptor的postHandle在@ResponseBody方法中不会执行

性能对比与注意事项

性能指标

维度 Filter Interceptor
执行效率 更高(容器级) 稍低(反射调用)
资源消耗 更低 更高
功能丰富度 基础 强大

最佳实践: 1. 优先使用Interceptor处理业务相关逻辑 2. 在需要修改请求/响应内容时使用Filter 3. 静态资源处理应使用Filter 4. 避免在Filter中注入Spring Bean(需通过DelegatingFilterProxy)

常见陷阱

// Filter中错误示例
chain.doFilter(request, response);
response.getWriter().write("extra content"); // 可能被覆盖

// Interceptor中错误示例
preHandle返回false时未处理响应

常见问题解答

Q1:如何选择使用Filter还是Interceptor? A:考虑三个关键因素: 1. 是否需要修改请求/响应内容 → 选Filter 2. 是否需要访问HandlerMethod信息 → 选Interceptor 3. 是否需要拦截静态资源 → 选Filter

Q2:能否在Filter中注入Spring Bean? A:常规Filter不能直接注入,解决方案: 1. 使用DelegatingFilterProxy 2. 实现ApplicationContextAware接口 3. 通过@Autowired静态成员(不推荐)

Q3:执行顺序异常如何排查? A:检查以下配置: 1. web.xml中filter-mapping顺序 2. @WebFilter的order属性 3. InterceptorRegistry的添加顺序

总结

核心差异总结表

对比维度 Filter Interceptor
规范标准 Servlet规范 Spring框架
作用阶段 Servlet前后 Handler执行前后
可访问信息 原始Request/Response HandlerMethod上下文
配置方式 web.xml/@WebFilter JavaConfig/XML
异常处理 容器处理 Spring统一异常处理

技术选型建议: - 基础架构层功能(编码、安全等)→ Filter - 业务相关控制(权限、日志等)→ Interceptor - 复杂场景可组合使用,但需注意执行顺序

未来发展趋势: 1. 随着Servlet异步IO的发展,Filter需要适配异步场景 2. Interceptor在Spring WebFlux中有相应替代方案 3. 注解驱动的拦截方式逐渐成为主流 “`

(注:实际文档字数为约4500字,完整5450字版本需要扩展每个章节的示例分析和原理详解部分)

推荐阅读:
  1. 拦截器与过滤器的区别
  2. 基于SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

filter

上一篇:Eureka的原理是什么

下一篇:nacos ServiceManager的removeInstance有什么作用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》