拦截器和过滤器的区别是什么

文章介绍了过滤器和拦截器在Web开发中的作用,包括它们的实现原理、生命周期方法、配置方式以及执行顺序。过滤器基于Servlet,实现Filter接口,拦截器是SpringMVC中的方法增强工具,实现HandlerInterceptor接口。过滤器在请求进入Servlet之前执行,拦截器则在进入Controller之前。两者在权限控制、日志、参数校验和跨域等问题上有不同的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

过滤器

过滤器Filter是基于Servlet实现。Servlet的工作原理是拦截配置好的客户端请求,然后对RequestResponse进行处理。Filter过滤器随着web应用的启动而启动,只初始化一次。

过滤器的配置比较简单,直接实现Filter 接口就可以了,也可以通过@WebFilter注解实现对特定URL拦截,Filter 接口中定义了三个方法:init()、doFilter()以及destroy()。

  • init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。注意:这个方法必须执行成功,否则过滤器会不起作用。

  • doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。

  • destroy(): 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次。

下面是的代码的实现方式:

package com.redis.test.filter;

import org.springframework.stereotype.Component;

import javax.servlet.*;
import java.io.IOException;

/**
 * @Author: laz
 * @CreateTime: 2023-03-01  17:21
 * @Version: 1.0
 */
@Component
public class TestFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
            System.err.println("过滤器前置");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.err.println("过滤器处理中");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        System.err.println("过滤器销毁");
    }
}

写一个测试类:

package com.redis.test.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author: laz
 * @CreateTime: 2023-03-01  09:39
 * @Version: 1.0
 */
@RestController
@RequestMapping("test")
public class TestController {


    @RequestMapping("filter")
    public void test(){
        System.err.println("controller逻辑代码");
    }
}

启动项目,执行此接口,然后查看控制台:

在这里插入图片描述
通过控制台输出日志可以看到:init()方法在容器启动初始化过滤器时被调用,doFilter()方法在请求接口的时候被调用,destroy()方法在容器销毁的时候才会被调用,一般看不到。

拦截器

拦截器是SpringMVC中实现的一种基于Java反射(动态代理)机制的方法增强工具,拦截器的实现方式是是实现HandlerInterceptor 接口,HandlerInterceptor接口里面也有三个方法:preHandle()postHandle()afterCompletion()

  • preHandle() :这个方法将在请求处理之前进行调用。注意:如果该方法的返回值为false ,将视为当前请求结束,不仅自身的拦截器会失效,还会导致其他的拦截器也不再执行。

  • postHandle():只有在 preHandle() 方法返回值为true 时才会执行。会在Controller中的方法调用之后,DispatcherServlet 返回渲染视图之前被调用。 有意思的是:postHandle() 方法被调用的顺序跟 preHandle() 是相反的,先声明的拦截器 preHandle() 方法先执行,而postHandle()方法反而会后执行。

  • afterCompletion():只有在 preHandle() 方法返回值为true 时才会执行。在整个请求结束之后, DispatcherServlet 渲染了对应的视图之后执行。

下面是的代码的实现方式:
先实现HandlerInterceptor接口并重写里面的三个方法:

package com.redis.test.interceptor;

import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Author: laz
 * @CreateTime: 2023-03-01  17:14
 * @Version: 1.0
 */
@Component
public class TestInterceptor implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.err.println("拦截器前置");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        System.err.println("拦截器处理中");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        System.err.println("拦截器后置");
    }

}

然后写一个配置类,将我们定义好的拦截器进行注册:

package com.redis.test.config;

import com.redis.test.interceptor.TestInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @Author: laz
 * @CreateTime: 2023-03-01  17:17
 * @Version: 1.0
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private TestInterceptor testInterceptor;


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        /**
         * addInterceptor(testInterceptor)将我们定义的拦截器进行注册
         * addPathPatterns("/**")表示对所有请求进行拦截
         * excludePathPatterns("/login")表示对某些请求放行,不需要拦截
         */
        registry.addInterceptor(testInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
    }
}

启动项目,再次调用我们上面的接口:

在这里插入图片描述

通过日志可以看到:preHandle()方法在请求处理前被调用,postHandle()方法在controller请求结束后被调用,而afterCompletion()方法是在整个请求结束后才被调用。

过滤器和拦截器的区别

从上面输出日志可以看到,过滤器是在拦截器之前被调用,下面提供两张过滤器与拦截器执行顺序图:

在这里插入图片描述

由图可知:过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后,过滤器属于Servlet级别。

拦截器Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束,拦截器属于Spring级别。

在这里插入图片描述

拦截器与过滤器执行顺序即:

过滤器前置->过滤器处理中->拦截器前置->拦截器处理中->拦截器后置->过滤器后置

在日常实际开发中拦截器的应用场景会比过滤器要更多,一般情况下他们的使用场景如下:

  • 拦截器:权限控制,日志打印,参数校验

  • 过滤器:跨域问题解决,编码转换

总结

拦截器和过滤器的区别主要有一下几点:

  1. 实现原理不同:过滤器拦截器 底层实现方式大不相同,过滤器 是基于函数回调的,拦截器 则是基于Java的反射机制(动态代理)实现的。
  2. 使用范围不同: 过滤器 实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。而拦截器它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。不仅能应用在web程序中,也可以用于Application等程序中。
  3. 触发时机不同: 由上图可知,过滤器优先于拦截器执行。
  4. 拦截的请求范围不同: 过滤器几乎可以对所有进入容器的请求起作用,而拦截器只会对Controller中请求或访问static目录下的资源请求起作用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值