Spring中的拦截器和过滤器

前言

Spring框架中的拦截器(Interceptor)和过滤器(Filter)是用于处理请求和响应的不同机制,但它们在Spring中的角色和实现方式有所不同。

1)过滤器(Filter):

  • 角色:Filter 是 Servlet 规范中定义的组件,用于在 Servlet 容器处理请求和响应之前或之后拦截这些请求和响应。

  • 实现:Filter 实现了 javax.servlet.Filter 接口,并在 web.xml 中配置或使用注解进行声明。

  • 实例代码:

@WebFilter(filterName = "exampleFilter", urlPatterns = "/*")
public class ExampleFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化代码
    }
 
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
        // 在请求处理前执行的逻辑
        chain.doFilter(request, response); // 传递请求到下一个过滤器或目标资源
        // 在请求处理后执行的逻辑
    }
 
    @Override
    public void destroy() {
        // 销毁代码
    }
}

 

2)拦截器(Interceptor):

  • 角色:Interceptor 是 Spring MVC 框架中的组件,用于在控制器方法处理之前、处理中和处理后添加行为。

  • 实现:Interceptor 实现了 org.springframework.web.servlet.HandlerInterceptor 接口,并在 Spring 配置中注册。

  • 实例代码:

public class ExampleInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
        throws Exception {
        // 在请求处理前执行的逻辑
        return true; // 继续请求处理
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 
        ModelAndView modelAndView) throws Exception {
        // 在请求处理后模型视图返回前执行的逻辑
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, 
        Exception ex) throws Exception {
        // 在完全处理完请求后执行的逻辑
    }
}

在 Spring 配置中注册拦截器:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new ExampleInterceptor());
    }
}

过滤器和拦截器的主要区别在于它们的实现方式和它们在请求处理生命周期中的位置:

  • Filter 在 Servlet 容器中工作,而拦截器是在 Spring MVC 框架中工作。

  • Filter 依赖于 Servlet 容器,而拦截器不依赖于 Servlet 容器,可以在任何 Servlet 或 Spring 应用程序中使用。

  • Filter 可以拦截所有类型的请求,而拦截器只能拦截发送到 Spring MVC 控制器的请求。

  • Filter 可以访问原始的 ServletRequest 和 ServletResponse,而拦截器只能访问包装过的 HttpServletRequest 和 HttpServletResponse。

过滤器的定义

过滤器是JavaWeb的三大组件之一,是实现Filter接口的Java类。

过滤器是实现对请求资源(jsp、servlet、html)的过滤功能,是一个运行在服务器的程序,优先于请求资源(jsp、servlet、html)之前执行。
当浏览器发送请求给服务器的时候,先执⾏过滤器,然后才访问Web的资源。服务器响应Response,从Web资源抵达浏览器之前,也会途径过滤器。

在很多Web开发中,都会用到过滤器(Filter),如参数过滤、防止SQL注入、防止页面攻击、过滤敏感字符、解决网站乱码、空参数矫正、Token验证、Session验证、点击率统计等。

代码案例

在启动类添加一个注解,找到定义的拦截器

@ServletComponentScan(basePackages = "com.binlog.study.filter")

写一个过滤器,实现Filter

@Slf4j
@Order(1)  //如果有多个Filter,则序号越小,越早被执行
//@Component//无需添加此注解,在启动类添加@ServletComponentScan注解后,会自动将带有@WebFilter的注解进行注入!
//这里的urlPatterns为接口里的路径过滤条件
@WebFilter(filterName = "timeFilter", urlPatterns = "/api/filter/*")
public class TimeFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("初始化过滤器:{}", filterConfig.getFilterName());
    }
    @Override
    public void destroy() {
        log.info("销毁过滤器");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("开始执行");
        long startTime = System.currentTimeMillis();
        filterChain.doFilter(servletRequest, servletResponse);
        long endTime = System.currentTimeMillis();
        log.info("请求:{},耗时:{}ms", getUrlFrom(servletRequest), (endTime - startTime));
        log.info("结束执行");
    }
    private String getUrlFrom(ServletRequest servletRequest) {
        if (servletRequest instanceof HttpServletRequest) {
            return ((HttpServletRequest) servletRequest).getRequestURL().toString();
        }
        return "";
    }
}

拦截器的定义

SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。

拦截器它是链式调用,一个应用中可以同时存在多个拦截器Interceptor,一个请求也可以触发多个拦截器,而每个拦截器的调用会依据它的声明顺序依次执行。

拦截器的核心API

SpringMVC拦截器提供三个方法分别是preHandle、postHandle、afterCompletion,我们就是通过重写这几个方法来对用户的请求进行拦截处理的。

  • preHandle() :这个方法将在请求处理之前进行调用。如果该方法的返回值为false ,将视为当前请求结束,不仅自身的拦截器会失效,还会导致其他的拦截器也不再执行。
  • postHandle():只有在 preHandle() 方法返回值为true 时才会执行。会在Controller 中的方法调用之后,DispatcherServlet 返回渲染视图之前被调用。postHandle() 方法被调用的顺序跟 preHandle() 是相反的,先声明的拦截器 preHandle() 方法先执行,而postHandle()方法反而会后执行。
  • afterCompletion():只有在 preHandle() 方法返回值为true 时才会执行,在整个请求结束之后, DispatcherServlet 渲染了对应的视图之后执行。

Interceptor 的应用场景:

  • 日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算 PV(Page View)等;

  • 权限检查:如登录检测,进入处理器检测是否登录;

  • 性能监控:通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间。(反向代理,如 Apache 也可以自动记录)

  • 通用行为:读取 Cookie 得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取 Locale、Theme 信息等,只要是多个处理器都需要的即可使用拦截器实现。

<think> 首先,用户的问题是关于Spring框架中拦截器过滤器的常见面试题。用户引用了站内内容[1],但我必须基于用户的真实需求来回应,而不是直接复制引用内容。用户明确说:“我想查找spring拦截器过滤器常见的面试题”,所以焦点是在面试题上。 回顾系统指令: - 所有行内数学表达式用$...$格式(但这里可能不涉及数学表达式)。 - 独立公式用$$...$$格式(可能不适用)。 - LaTeX语法正确(确保在需要时使用)。 - 使用中文回答。 - 生成相关问题。 - 引用的段落末尾添加引用标识(但我没有外部引用,只有用户提供的[1])。 用户提供的引用[1]是关于过滤器拦截器的区别,但它不是用户真正的需求;用户想要面试题。所以,我应该基于自己的知识生成Spring拦截器过滤器的常见面试题。 结构化回答: - 回答应清晰、逐步解决问题。 - 确保真实可靠。 - 最后生成相关问题。 关键点: - Spring框架中,拦截器Spring MVC的一部分,而过滤器是Servlet API的一部分。 - 常见面试题包括区别、用途、配置方式等。 列出可能的常见面试题: 1. 过滤器拦截器的区别是什么? 2. 如何在Spring中配置过滤器? 3. 如何在Spring MVC中配置拦截器? 4. 过滤器拦截器的执行顺序是怎样的? 5. 实际应用场景举例。 6. 优缺点比较。 7. 如何自定义拦截器过滤器? 从引用[1]中提取有用信息: - 运行位置不同:过滤器在Web服务器Servlet容器之间,拦截器在控制器内部。 - 执行顺序:过滤器由web.xml顺序决定,拦截器由配置文件声明顺序决定。 - 功能不同:过滤器用于预处理(如字符集设置、登录验证),拦截器用于流程控制(如权限验证、参数注入)。 - 依赖框架:过滤器不依赖特定框架,拦截器通常依赖Spring MVC。 现在,生成面试题: - 基于上述,构建问题列表。 回答结构: 1. 先简要概述过滤器拦截器Spring中的作用。 2. 然后列出常见面试题。 3. 最后生成相关问题。 生成相关问题(根据指令6): - 在回答末尾添加相关问题部分。 使用中文回答。 最终回答大纲: - 开头:概述Spring过滤器拦截器的角色。 - 主体:列出常见面试题。 - 结尾:生成相关问题。 </think> ### Spring框架中过滤器拦截器常见面试题解析 在Java Web开发中,Spring框架广泛使用过滤器拦截器来处理HTTP请求响应。过滤器(Filter)基于Servlet规范,作用于Web容器层面;拦截器(Interceptor)是Spring MVC特有的组件,针对控制器方法进行拦截。以下是常见的面试题大全,基于Spring实际应用最佳实践整理。这些问题涵盖了核心概念、区别、配置使用场景,帮助您系统准备面试。 #### 常见面试题列表 1. **过滤器拦截器的主要区别是什么?** - 过滤器在请求进入Servlet容器前处理(如Tomcat),而拦截器Spring MVC控制器前后执行。 - 过滤器优先级更低,依赖`web.xml`配置;拦截器优先级更高,依赖Spring配置文件(如`@Configuration`类)。 - 功能上:过滤器常用于全局任务(如字符编码设置、日志记录),拦截器更适合业务逻辑处理(如权限验证、参数校验)[^1]。 2. **如何在Spring Boot中配置一个自定义过滤器?** - 示例:通过实现`javax.servlet.Filter`接口,并在`@Configuration`类中使用`@Bean`注册。例如: ```java @Bean public Filter myFilter() { return new Filter() { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 预处理逻辑(如登录检查) chain.doFilter(request, response); // 传递给下一个过滤器 // 后处理逻辑 } }; } ``` - 面试考点:过滤器执行顺序如何控制?通过`FilterRegistrationBean`设置`@Order`注解调整优先级。 3. **如何在Spring MVC中实现一个自定义拦截器?** - 步骤:继承`HandlerInterceptorAdapter`或实现`HandlerInterceptor`接口,重写`preHandle`(控制器前执行)、`postHandle`(控制器后执行)、`afterCompletion`(请求完成后执行)方法。 - 配置:在`@Configuration`类中添加拦截器到`InterceptorRegistry`: ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/api/**"); // 仅拦截/api路径 } } ``` - 面试考点:拦截器与AOP(面向切面编程)的区别?拦截器针对HTTP请求,AOP更通用(如事务管理)。 4. **过滤器拦截器的执行顺序是怎样的?举例说明。** - 过滤器顺序:按`web.xml`或`@Order`声明顺序执行(先声明先执行)。 - 拦截器顺序:按添加顺序执行(`preHandle`按添加顺序,`postHandle``afterCompletion`倒序)。 - 示例场景:多个过滤器拦截器链式调用时,过滤器先于拦截器执行。例如,登录验证过滤器(全局)→ 权限拦截器(控制器级)。 5. **实际应用中,过滤器拦截器各有哪些典型使用场景?** - 过滤器:处理跨域问题(CORS)、请求日志记录、字符编码统一设置。 - 拦截器Spring MVC中的用户认证(如JWT校验)、性能监控、参数注入或修改。 - 面试考点:为什么权限验证通常用拦截器而非过滤器?因为拦截器能精确控制控制器方法,减少性能开销[^1]。 6. **Spring Boot中如何处理过滤器拦截器的异常?** - 过滤器异常:通过`FilterChain`抛出,需在`web.xml`或Spring配置中定义错误页面。 - 拦截器异常:在`afterCompletion`方法中处理,或结合`@ControllerAdvice`全局异常处理器。 - 面试考点:如何避免过滤器/拦截器导致的循环调用?确保逻辑简洁,避免重定向或重复处理。 7. **过滤器拦截器的性能影响如何优化?** - 优化策略:减少不必要的拦截路径(使用`excludePathPatterns`)、缓存重复计算结果、异步处理日志。 - 对比:过滤器因全局作用可能更耗性能,拦截器更轻量级但需Spring上下文支持。 8. **Spring MVC拦截器与Servlet过滤器的集成兼容性问题?** - 问题:当同时使用时,可能出现执行顺序冲突(如过滤器修改请求后,拦截器读取无效)。 - 解决方案:明确划分职责(过滤器处理容器级任务,拦截器处理业务逻辑),并通过配置调整优先级。 以上问题基于Spring 5.xSpring Boot 2.x版本,参考常见面试题库实践经验整理。确保在回答时结合实际代码示例加深理解。 相关问题: 1. Spring MVC拦截器如何实现登录验证? 2. 在Spring Boot中如何测试过滤器拦截器的功能? 3. 过滤器拦截器在微服务架构中的应用有哪些挑战? 4. Spring Security与过滤器拦截器的关系是什么? 5. 如何监控过滤器拦截器的性能指标?
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值