在 SpringMVC 中,拦截器(Interceptor)和过滤器(Filter)都用于对请求进行预处理或后处理,但它们在所属规范、作用范围、执行时机等方面有显著区别,具体如下:

1. 所属规范不同

  • 过滤器(Filter):属于Java EE Servlet 规范的一部分,是 Servlet 容器(如 Tomcat)层面的组件,不依赖于 Spring 框架,可在任何 Java Web 项目中使用。
  • 拦截器(Interceptor):是SpringMVC 框架自身提供的组件,依赖于 Spring 容器,仅在 SpringMVC 项目中生效。

2. 实现接口不同

  • 过滤器:需实现 javax.servlet.Filter 接口,核心方法为 doFilter(ServletRequest, ServletResponse, FilterChain)
  • 拦截器:需实现 org.springframework.web.servlet.HandlerInterceptor 接口,核心方法为:
    • preHandle:Controller 方法执行前调用;
    • postHandle:Controller 方法执行后、视图渲染前调用;
    • afterCompletion:视图渲染完成后调用。

3. 作用范围不同

  • 过滤器:可拦截所有请求(包括静态资源如 CSS/JS、JSP、Servlet、非 SpringMVC 处理的请求等),只要在配置的 urlPatterns 范围内都会被拦截。
  • 拦截器:仅拦截SpringMVC 处理的请求(即通过 DispatcherServlet 分发到 Controller 的请求),对静态资源、非 SpringMVC 管理的 Servlet 等请求不生效(除非特殊配置)。

4. 执行时机不同

  • 过滤器:在请求进入 Servlet 容器后、Servlet(如 DispatcherServlet)处理前执行,且在响应返回给客户端前也可能执行(通过 FilterChain 传递)。
  • 拦截器:在 DispatcherServlet 处理请求的过程中执行,具体阶段由其三个方法决定:
    • preHandle:DispatcherServlet 调用 Controller 前;
    • postHandle:Controller 执行完但视图未渲染前;
    • afterCompletion:视图渲染完成后。

5. 生命周期管理不同

  • 过滤器:由 Servlet 容器(如 Tomcat)管理生命周期,随容器启动而初始化(init 方法),随容器关闭而销毁(destroy 方法)。
  • 拦截器:由 Spring 容器管理,属于 Spring 的 Bean,可通过 Spring 的依赖注入(DI)获取其他 Bean,参与 Spring 的生命周期(如初始化、销毁回调)。

6. 配置方式不同

  • 过滤器:
    • 传统方式:在 web.xml 中配置 <filter> 和 <filter-mapping>
    • 注解方式:使用 @WebFilter 注解,并通过 Servlet 容器扫描生效。
  • 拦截器:需在 SpringMVC 配置类中通过 WebMvcConfigurer 的 addInterceptors 方法注册,例如:
    java
     
    运行
     
     
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new MyInterceptor())
                    .addPathPatterns("/**") // 拦截路径
                    .excludePathPatterns("/login"); // 排除路径
        }
    }
    
      

7. 可访问的资源不同

  • 过滤器:仅能访问 ServletRequest 和 ServletResponse 对象,无法直接获取 SpringMVC 的内部组件(如 Controller 方法、ModelAndView 等)。
  • 拦截器:可通过参数直接获取 HandlerMethod(当前执行的 Controller 方法)、ModelAndView 等 SpringMVC 内部对象,能更精细地控制请求流程。

8. 典型应用场景

  • 过滤器:常用于通用功能,如字符编码设置(CharacterEncodingFilter)、跨域处理(CorsFilter)、敏感词过滤、请求日志记录等。
  • 拦截器:常用于与业务相关的功能,如登录状态验证、权限校验、Controller 方法执行时间统计、事务管理等。

总结

过滤器是 Servlet 层面的 “全局拦截”,作用范围更广但功能较基础;拦截器是 SpringMVC 层面的 “精细拦截”,依赖 Spring 容器,可深度集成业务逻辑。实际开发中,两者可配合使用(如过滤器处理编码,拦截器处理登录验证)。
 
分别给出SpringMVC拦截器和过滤器的代码示例
 
已完成思考
 
 
下面分别给出 SpringMVC 拦截器和过滤器的代码示例,结合实际场景(拦截器实现登录验证,过滤器实现请求日志记录)进行说明。

一、过滤器(Filter)示例

场景:记录所有请求的 URL、方法及执行时间,基于 Servlet 规范实现。

1. 过滤器实现类

java
 
运行
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;

// 注解方式配置过滤器:拦截所有请求(/*)
@WebFilter(urlPatterns = "/*", filterName = "logFilter")
public class LogFilter implements Filter {

    // 过滤器初始化(容器启动时执行)
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("LogFilter初始化...");
    }

    // 核心过滤逻辑
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        // 1. 预处理:记录请求开始时间、URL、方法
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String url = httpRequest.getRequestURL().toString();
        String method = httpRequest.getMethod();
        long startTime = new Date().getTime();
        System.out.println("====== 请求开始:" + method + " " + url + " ======");

        // 2. 放行请求(继续执行后续过滤器或Servlet)
        chain.doFilter(request, response); // 必须调用,否则请求会被拦截

        // 3. 后处理:记录请求结束时间和耗时
        long endTime = new Date().getTime();
        System.out.println("====== 请求结束:耗时 " + (endTime - startTime) + "ms ======\n");
    }

    // 过滤器销毁(容器关闭时执行)
    @Override
    public void destroy() {
        System.out.println("LogFilter销毁...");
    }
}
 

2. 过滤器生效配置(Spring Boot 环境)

在 Spring Boot 启动类上添加@ServletComponentScan注解,开启 Servlet 组件扫描(使@WebFilter生效):
 
java
 
运行
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
@ServletComponentScan // 扫描Servlet组件(Filter、Servlet、Listener)
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
 
 
说明:传统 Web 项目可在web.xml中配置过滤器,替代注解方式:
xml
 
<filter>
    <filter-name>logFilter</filter-name>
    <filter-class>com.example.filter.LogFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>logFilter</filter-name>
    <url-pattern>/*</url-pattern> <!-- 拦截所有请求 -->
</filter-mapping>
 

二、拦截器(Interceptor)示例

场景:验证用户是否登录(检查 Session 中是否有用户信息),未登录则重定向到登录页,基于 SpringMVC 框架实现。

1. 拦截器实现类

java
运行
 
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginInterceptor implements HandlerInterceptor {

    // Controller方法执行前调用(核心拦截逻辑)
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
            throws Exception {
        // 1. 获取Session
        HttpSession session = request.getSession();
        Object user = session.getAttribute("loginUser"); // 假设登录后用户信息存于Session的"loginUser"键

        // 2. 验证登录状态
        if (user == null) {
            // 未登录:重定向到登录页
            response.sendRedirect(request.getContextPath() + "/login");
            return false; // 中断请求,不再执行后续Controller
        } else {
            // 已登录:放行
            return true; // 继续执行Controller方法
        }
    }

    // Controller方法执行后、视图渲染前调用
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 
                           ModelAndView modelAndView) throws Exception {
        // 可在这里修改ModelAndView(如添加公共数据)
        if (modelAndView != null) {
            modelAndView.addObject("currentTime", System.currentTimeMillis());
        }
    }

    // 视图渲染完成后调用(通常用于资源清理)
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, 
                                Exception ex) throws Exception {
        // 例如:记录异常日志
        if (ex != null) {
            System.out.println("请求处理异常:" + ex.getMessage());
        }
    }
}
 

2. 拦截器注册配置

通过 SpringMVC 配置类注册拦截器,并指定拦截 / 排除路径:
 
java
 
运行
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration // 标识为配置类
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册登录拦截器
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**") // 拦截所有路径
                .excludePathPatterns( // 排除不需要拦截的路径(登录页、静态资源等)
                        "/login", 
                        "/doLogin", // 登录提交接口
                        "/css/**", 
                        "/js/**", 
                        "/images/**"
                );
    }
}

关键区别体现

  • 过滤器的doFilter方法需要手动调用chain.doFilter放行,而拦截器通过preHandle的返回值(true/false)控制是否放行。
  • 拦截器可直接操作ModelAndView等 SpringMVC 内部对象(如postHandle方法),过滤器仅能访问ServletRequest/ServletResponse
  • 过滤器拦截所有请求(包括静态资源),拦截器仅拦截 SpringMVC 管理的请求(通过DispatcherServlet的请求)
posted on 2025-10-17 16:22  从精通到陌生  阅读(3)  评论(0)    收藏  举报