Deprecated: 自 6.9.0 版本起,使用参数调用函数 WP_Dependencies->add_data() 已弃用!IE conditional comments are ignored by all supported browsers. in D:\wwwroot\zyxy\wordpress\wp-includes\functions.php on line 6131

Deprecated: 自 6.9.0 版本起,使用参数调用函数 WP_Dependencies->add_data() 已弃用!IE conditional comments are ignored by all supported browsers. in D:\wwwroot\zyxy\wordpress\wp-includes\functions.php on line 6131

Spring MVC:拦截器(Interceptor)与过滤器(Filter)

各位观众老爷,各位技术大咖,以及各位正在努力秃头的程序员们,大家好!我是你们的老朋友,一个在代码海洋里摸爬滚打多年的老水手。今天,咱们来聊聊Spring MVC框架中的两位“门卫”——拦截器(Interceptor)和过滤器(Filter)。

这俩哥们儿,名字听起来就挺像,都是用来过滤请求,进行一些预处理或者后处理的。但是,就像双胞胎兄弟,虽然长得像,性格和职责却大相径庭。今天,咱们就拨开迷雾,看看他们到底有啥区别,以及在实际项目中该如何正确使用。

一、开场白:请求的旅程

想象一下,一个HTTP请求就像一位远道而来的客人,想要拜访咱们精心搭建的Spring MVC城堡🏰。这位客人必须经过重重关卡,才能最终到达城堡的核心,也就是咱们的Controller。

而拦截器和过滤器,就像是矗立在城堡门口的两道岗哨,负责对客人进行检查和引导。他们可以在客人进入城堡之前,或者离开城堡之后,做一些事情,比如:

  • 验证客人的身份(权限控制)
  • 记录客人的行踪(日志记录)
  • 修改客人的穿着打扮(请求/响应内容修改)
  • 甚至直接把不速之客拒之门外(阻止请求)

二、过滤器(Filter):入门级的“门卫”

过滤器,可以理解为最基础的“门卫”。它属于Servlet规范的一部分,脱离Spring MVC也能独立存在。它拦截的是所有进入Web应用的请求,无论这些请求最终是否会到达Spring MVC。

1. 过滤器的工作原理

过滤器的工作原理很简单,就是通过配置,指定哪些URL需要经过该过滤器的处理。当一个请求到达Web应用时,如果请求的URL匹配了过滤器的配置,那么该过滤器就会被激活,执行其中的代码。

2. 过滤器的生命周期

过滤器的生命周期由Servlet容器(比如Tomcat)管理,它主要有三个阶段:

  • 初始化(init): 容器启动时,会创建过滤器实例,并调用init方法进行初始化。
  • 过滤(doFilter): 每次请求到达时,如果匹配过滤器的配置,就会调用doFilter方法进行处理。在这个方法中,你可以对请求和响应进行修改,也可以决定是否将请求传递给下一个过滤器或者Servlet。
  • 销毁(destroy): 容器关闭时,会调用destroy方法进行清理。

3. 过滤器的适用场景

由于过滤器拦截的是所有请求,因此它通常用于处理一些与Spring MVC无关的通用任务,比如:

  • 字符编码转换: 确保请求和响应使用统一的字符编码,避免乱码问题。
  • 静态资源过滤: 过滤掉对静态资源(比如图片、CSS、JavaScript)的请求,避免不必要的处理。
  • XSS攻击防御: 过滤掉请求中的恶意脚本,防止XSS攻击。
  • Session管理: 检查用户是否已经登录,如果没有登录则重定向到登录页面。

4. 过滤器的代码示例

下面是一个简单的字符编码过滤器示例:

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebFilter(urlPatterns = "/*") // 拦截所有请求
public class CharacterEncodingFilter implements Filter {

    private String encoding = "UTF-8";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String encodingParam = filterConfig.getInitParameter("encoding");
        if (encodingParam != null) {
            encoding = encodingParam;
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        httpRequest.setCharacterEncoding(encoding);
        httpResponse.setCharacterEncoding(encoding);
        httpResponse.setContentType("text/html;charset=" + encoding);

        chain.doFilter(request, response); // 将请求传递给下一个过滤器或Servlet
    }

    @Override
    public void destroy() {
        // 释放资源
    }
}

表格总结:过滤器

特性 说明
所属规范 Servlet规范
拦截范围 所有进入Web应用的请求
生命周期 由Servlet容器管理
应用场景 字符编码转换、静态资源过滤、XSS攻击防御、Session管理等通用任务
对Spring的依赖

三、拦截器(Interceptor):Spring MVC的“贴身保镖”

拦截器,是Spring MVC框架特有的组件。它拦截的是经过DispatcherServlet处理的请求,也就是那些真正进入Spring MVC流程的请求。

1. 拦截器的工作原理

拦截器的工作原理与过滤器类似,也是通过配置,指定哪些URL需要经过该拦截器的处理。但是,拦截器的配置更加灵活,可以根据Spring MVC的HandlerMapping进行更精确的匹配。

2. 拦截器的生命周期

拦截器的生命周期由Spring MVC框架管理,它主要有三个阶段:

  • preHandle: 在Controller处理请求之前调用。你可以在这里进行权限验证、日志记录等操作,甚至可以直接阻止请求的执行。
  • postHandle: 在Controller处理请求之后,但在视图渲染之前调用。你可以在这里对ModelAndView进行修改,添加一些额外的参数或者数据。
  • afterCompletion: 在整个请求处理完成之后调用,包括视图渲染完成之后。你可以在这里进行资源清理、异常处理等操作。

3. 拦截器的适用场景

由于拦截器只拦截经过DispatcherServlet处理的请求,因此它通常用于处理一些与Spring MVC相关的任务,比如:

  • 权限控制: 检查用户是否具有访问Controller的权限。
  • 日志记录: 记录Controller的执行时间、请求参数等信息。
  • 数据绑定: 在Controller处理请求之前,对请求参数进行预处理,比如格式化日期、trim字符串等。
  • 国际化处理: 根据用户的语言环境,设置相应的Locale。

4. 拦截器的代码示例

下面是一个简单的权限控制拦截器示例:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // 检查用户是否登录
        if (request.getSession().getAttribute("user") == null) {
            response.sendRedirect(request.getContextPath() + "/login");
            return false; // 阻止请求继续执行
        }
        return true; // 允许请求继续执行
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        // 可以对ModelAndView进行修改
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // 可以进行资源清理
    }
}

表格总结:拦截器

特性 说明
所属规范 Spring MVC框架
拦截范围 经过DispatcherServlet处理的请求
生命周期 由Spring MVC框架管理
应用场景 权限控制、日志记录、数据绑定、国际化处理等与Spring MVC相关的任务
对Spring的依赖

四、拦截器与过滤器的区别:一场“门卫”之间的对话

现在,咱们来总结一下拦截器和过滤器的区别,就像两位“门卫”之间的对话:

过滤器: “我是Web应用的大门,啥请求都得经过我这儿,Servlet规范让我这么干的!”

拦截器: “我是Spring MVC城堡的守卫,只有经过DispatcherServlet的客人才能见到我,Spring MVC框架让我这么干的!”

具体区别如下表所示:

特性 过滤器(Filter) 拦截器(Interceptor)
所属规范 Servlet规范 Spring MVC框架
拦截范围 所有进入Web应用的请求 经过DispatcherServlet处理的请求
生命周期 由Servlet容器管理 由Spring MVC框架管理
实现方式 实现javax.servlet.Filter接口 实现org.springframework.web.servlet.HandlerInterceptor接口
应用场景 字符编码转换、静态资源过滤、XSS攻击防御、Session管理等 权限控制、日志记录、数据绑定、国际化处理等
获取Spring Bean 不方便,需要通过ServletContext获取 方便,可以通过依赖注入获取
使用范围 通用,适用于各种Web应用 局限于Spring MVC框架

五、实战演练:如何选择合适的“门卫”?

那么,在实际项目中,我们该如何选择使用过滤器还是拦截器呢?

记住以下几点:

  • 通用任务,选择过滤器: 如果你的任务与Spring MVC无关,比如字符编码转换、静态资源过滤等,那么选择过滤器是最佳方案。
  • Spring MVC相关任务,选择拦截器: 如果你的任务与Spring MVC紧密相关,比如权限控制、日志记录、数据绑定等,那么选择拦截器是更合适的选择。
  • 职责分离,避免过度耦合: 尽量将通用任务放在过滤器中处理,将Spring MVC相关任务放在拦截器中处理,保持代码的清晰和可维护性。
  • 灵活配置,满足不同需求: 过滤器和拦截器都支持灵活的配置,可以根据不同的URL模式或者请求类型,选择不同的处理方式。

六、进阶技巧:链式调用与执行顺序

无论是过滤器还是拦截器,都可以配置多个。当多个过滤器或拦截器同时作用于同一个请求时,它们的执行顺序就显得尤为重要。

  • 过滤器链: 多个过滤器组成一个过滤器链,它们的执行顺序由web.xml或者@WebFilter注解的filterName属性决定。filterName越靠前的过滤器,执行顺序越靠前。
  • 拦截器链: 多个拦截器组成一个拦截器链,它们的执行顺序由Spring MVC的配置决定。在WebMvcConfigurer中,可以通过addInterceptors方法添加拦截器,添加的顺序决定了它们的执行顺序。

注意:

  • 过滤器链和拦截器链是独立的,它们之间没有直接的关联。
  • 在过滤器链中,如果某个过滤器调用了chain.doFilter方法,那么请求会继续传递给下一个过滤器或者Servlet。如果某个过滤器没有调用chain.doFilter方法,那么请求会被中断,不会继续传递下去。
  • 在拦截器链中,如果某个拦截器的preHandle方法返回false,那么请求会被中断,不会继续传递给下一个拦截器或者Controller。

七、总结:让请求的旅程更加安全、高效

总而言之,拦截器和过滤器都是Spring MVC框架中重要的组成部分,它们可以帮助我们对请求进行预处理和后处理,实现各种各样的功能。

记住,过滤器是入门级的“门卫”,拦截所有请求;拦截器是Spring MVC的“贴身保镖”,只拦截经过DispatcherServlet处理的请求。

选择合适的“门卫”,合理配置它们的执行顺序,可以让我们的Web应用更加安全、高效、易于维护。

希望这篇文章能帮助大家更好地理解Spring MVC中的拦截器和过滤器,并在实际项目中灵活运用它们,让你的代码更加优雅、高效!

最后,祝大家编码愉快,早日摆脱秃头危机!💪😄

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注