我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

本篇内容介绍了“过滤器和拦截器的区别是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

我们在项目中同时配置 拦截器过滤器

过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接口中定义了三个方法。

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

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

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

@Componentpublic class MyFilter implements Filter {        @Override    public void init(FilterConfig filterConfig) throws ServletException {        System.out.println("Filter 前置");    }    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        System.out.println("Filter 处理中");        filterChain.doFilter(servletRequest, servletResponse);    }    @Override    public void destroy() {        System.out.println("Filter 后置");    }}

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

首先编写一个简单的拦截器处理类,请求的拦截是通过HandlerInterceptor 来实现,看到HandlerInterceptor 接口中也定义了三个方法。

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

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

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

@Componentpublic class MyInterceptor implements HandlerInterceptor {    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        System.out.println("Interceptor 前置");        return true;    }    @Override    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {        System.out.println("Interceptor 处理中");    }    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {        System.out.println("Interceptor 后置");    }}

将自定义好的拦截器处理类进行注册,并通过addPathPatternsexcludePathPatterns等属性设置需要拦截或需要排除的 URL

@Configurationpublic class MyMvcConfig implements WebMvcConfigurer {    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");        registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**");    }}

过滤器 和 拦截器 均体现了AOP的编程思想,都可以实现诸如日志记录、登录鉴权等功能,但二者的不同点也是比较多的,接下来一一说明。

过滤器和拦截器 底层实现方式大不相同,过滤器 是基于函数回调的,拦截器 则是基于Java的反射机制(动态代理)实现的。

这里重点说下过滤器!

在我们自定义的过滤器中都会实现一个 doFilter()方法,这个方法有一个FilterChain 参数,而实际上它是一个回调接口。ApplicationFilterChain是它的实现类, 这个实现类内部也有一个 doFilter() 方法就是回调方法。

public interface FilterChain {    void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;}
过滤器和拦截器的区别是什么

ApplicationFilterChain里面能拿到我们自定义的xxxFilter类,在其内部回调方法doFilter()里调用各个自定义xxxFilter过滤器,并执行 doFilter() 方法。

public final class ApplicationFilterChain implements FilterChain {    @Override    public void doFilter(ServletRequest request, ServletResponse response) {            ...//省略            internalDoFilter(request,response);    }     private void internalDoFilter(ServletRequest request, ServletResponse response){    if (pos < n) {            //获取第pos个filter                ApplicationFilterConfig filterConfig = filters[pos++];                    Filter filter = filterConfig.getFilter();            ...            filter.doFilter(request, response, this);        }    } }

而每个xxxFilter 会先执行自身的 doFilter() 过滤逻辑,最后在执行结束前会执行filterChain.doFilter(servletRequest, servletResponse),也就是回调ApplicationFilterChaindoFilter() 方法,以此循环执行实现函数回调。

    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        filterChain.doFilter(servletRequest, servletResponse);    }

我们看到过滤器 实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。

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

而拦截器(Interceptor)  它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。不仅能应用在web程序中,也可以用于ApplicationSwing等程序中。

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

过滤器拦截器的触发时机也不同,我们看下边这张图。

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

过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。

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

在上边我们已经同时配置了过滤器和拦截器,再建一个Controller接收请求测试一下。

@Controller@RequestMapping()public class Test {    @RequestMapping("/test1")    @ResponseBody    public String test1(String a) {        System.out.println("我是controller");        return null;    }}

项目启动过程中发现,过滤器的init()方法,随着容器的启动进行了初始化。

过滤器和拦截器的区别是什么在这里插入图片描述

此时浏览器发送请求,F12 看到居然有两个请求,一个是我们自定义的 Controller 请求,另一个是访问静态图标资源的请求。

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

看到控制台的打印日志如下:

执行顺序 :Filter 处理中 -> Interceptor 前置 -> 我是controller -> Interceptor 处理中 -> Interceptor 处理后

Filter 处理中Interceptor 前置Interceptor 处理中Interceptor 后置Filter 处理中

过滤器Filter执行了两次,拦截器Interceptor只执行了一次。这是因为过滤器几乎可以对所有进入容器的请求起作用,而拦截器只会对Controller中请求或访问static目录下的资源请求起作用。

在实际的业务场景中,应用到过滤器或拦截器,为处理业务逻辑难免会引入一些service服务。

下边我们分别在过滤器和拦截器中都注入service,看看有什么不同?

@Componentpublic class TestServiceImpl implements TestService {    @Override    public void a() {        System.out.println("我是方法A");    }}

过滤器中注入service,发起请求测试一下 ,日志正常打印出“我是方法A”

@Autowired    private TestService testService;    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        System.out.println("Filter 处理中");        testService.a();        filterChain.doFilter(servletRequest, servletResponse);    }
Filter 处理中我是方法AInterceptor 前置我是controllerInterceptor 处理中Interceptor 后置

在拦截器中注入service,发起请求测试一下 ,竟然TM的报错了,debug跟一下发现注入的service怎么是Null啊?

过滤器和拦截器的区别是什么在这里插入图片描述

这是因为加载顺序导致的问题,拦截器加载的时间点在springcontext之前,而Bean又是由spring进行管理。

拦截器:老子今天要进洞房;

Spring:兄弟别闹,你媳妇我还没生出来呢!

解决方案也很简单,我们在注册拦截器之前,先将Interceptor 手动进行注入。注意:在registry.addInterceptor()注册的是getMyInterceptor() 实例。

@Configurationpublic class MyMvcConfig implements WebMvcConfigurer {    @Bean    public MyInterceptor getMyInterceptor(){        System.out.println("注入了MyInterceptor");        return new MyInterceptor();    }        @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(getMyInterceptor()).addPathPatterns("/**");    }}

实际开发过程中,会出现多个过滤器或拦截器同时存在的情况,不过,有时我们希望某个过滤器或拦截器能优先执行,就涉及到它们的执行顺序。

过滤器用@Order注解控制执行顺序,通过@Order控制过滤器的级别,值越小级别越高越先执行。

@Order(Ordered.HIGHEST_PRECEDENCE)@Componentpublic class MyFilter2 implements Filter {

拦截器默认的执行顺序,就是它的注册顺序,也可以通过Order手动设置控制,值越小越先执行。

 @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**").order(2);        registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**").order(1);        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").order(3);    }

看到输出结果发现,先声明的拦截器  preHandle() 方法先执行,而postHandle()方法反而会后执行。

postHandle() 方法被调用的顺序跟 preHandle() 居然是相反的!如果实际开发中严格要求执行顺序,那就需要特别注意这一点。

Interceptor1 前置Interceptor2 前置Interceptor 前置我是controllerInterceptor 处理中Interceptor2 处理中Interceptor1 处理中Interceptor 后置Interceptor2 处理后Interceptor1 处理后

那为什么会这样呢?  得到答案就只能看源码了,我们要知道controller 中所有的请求都要经过核心组件DispatcherServlet路由,都会执行它的 doDispatch() 方法,而拦截器postHandle()preHandle()方法便是在其中调用的。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {            try {         ...........            try {                           // 获取可以执行当前Handler的适配器                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());                // Process last-modified header, if supported by the handler.                String method = request.getMethod();                boolean isGet = "GET".equals(method);                if (isGet || "HEAD".equals(method)) {                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());                    if (logger.isDebugEnabled()) {                        logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);                    }                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {                        return;                    }                }                // 注意: 执行Interceptor中PreHandle()方法                if (!mappedHandler.applyPreHandle(processedRequest, response)) {                    return;                }                // 注意:执行Handle【包括我们的业务逻辑,当抛出异常时会被Try、catch到】                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());                if (asyncManager.isConcurrentHandlingStarted()) {                    return;                }                applyDefaultViewName(processedRequest, mv);                // 注意:执行Interceptor中PostHandle 方法【抛出异常时无法执行】                mappedHandler.applyPostHandle(processedRequest, response, mv);            }        }        ...........    }

看看两个方法applyPreHandle()applyPostHandle()具体是如何被调用的,就明白为什么postHandle()preHandle()  执行顺序是相反的了。

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {        HandlerInterceptor[] interceptors = this.getInterceptors();        if(!ObjectUtils.isEmpty(interceptors)) {            for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {                HandlerInterceptor interceptor = interceptors[i];                if(!interceptor.preHandle(request, response, this.handler)) {                    this.triggerAfterCompletion(request, response, (Exception)null);                    return false;                }            }        }        return true;    }
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {        HandlerInterceptor[] interceptors = this.getInterceptors();        if(!ObjectUtils.isEmpty(interceptors)) {            for(int i = interceptors.length - 1; i >= 0; --i) {                HandlerInterceptor interceptor = interceptors[i];                interceptor.postHandle(request, response, this.handler, mv);            }        }    }

发现两个方法中在调用拦截器数组 HandlerInterceptor[] 时,循环的顺序竟然是相反的。。。,导致postHandle()preHandle() 方法执行的顺序相反。

“过滤器和拦截器的区别是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

本篇内容介绍了“过滤器和拦截器的区别是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!我们在项目中同时配置 拦截器 和 过滤器。过滤器的配
2023-06-02

java拦截器和过滤器有什么区别

Java拦截器和过滤器都是用于处理请求和响应的中间件,但它们在功能和使用方面有一些区别。功能:拦截器主要用于处理方法级别的拦截和处理,可以拦截请求的方法调用和响应的结果。过滤器主要用于处理请求和响应的内容,可以对请求和响应的数据进行修改、过
2023-10-24

Spring拦截器和过滤器有什么区别

今天就跟大家聊聊有关Spring拦截器和过滤器有什么区别,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、概述拦截器和过滤器filter和拦截器的功能都是拦截,filter拦截的目标
2023-06-15

Java中拦截器和过滤器有什么区别

这篇文章将为大家详细讲解有关Java中拦截器和过滤器有什么区别,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、过滤器(filter)过滤器处于客户端与Web资源(Servlet、JSP、HTML)之间,
2023-06-15

java中过滤器和拦截器有什么区别

在Java中,过滤器(Filter)和拦截器(Interceptor)都是用于处理Web请求的组件,但它们有以下区别:1. 功能不同:过滤器主要用于在请求被发送到Servlet或JSP之前预处理请求和响应,例如验证用户身份、编码转换、日志记
2023-08-26

Java中的过滤器和拦截器有什么区别么?

我们自定义一个获取并返回某个静态资源的内容以及整个请求所花费的时间拦截器,一般这个还是比较有用的,而且还可以加一个请求访问的,然后来处理方法执行时间的。

面试官:过滤器和拦截器有什么区别?

过滤器和拦截器都是基于 AOP 思想实现的,用来处理某个统一的功能的,但二者又有 5 点不同:出身不同、触发时机不同、实现不同、支持的项目类型不同以及使用的场景不同。过滤器通常是用来进行全局过滤的,而拦截器是用来实现某项业务拦截的。

Java 拦截器与过滤器的区别究竟有哪些?(java拦截器和过滤器的区别有哪些)

在Java开发中,拦截器(Interceptor)和过滤器(Filter)是两个常用的概念,它们都可以用于在请求处理的不同阶段进行拦截和处理,但在实现方式、使用场景等方面存在一些区别。一、实现方式
Java 拦截器与过滤器的区别究竟有哪些?(java拦截器和过滤器的区别有哪些)
Java2024-12-13

Java拦截器和过滤器的区别有哪些

小编给大家分享一下Java拦截器和过滤器的区别有哪些,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、过滤器(filter)过滤器处于客户端与Web资源(Servlet、JSP、HTML)之间,客户端与Web资源之间的请求
2023-06-15

过滤器Filter和拦截器Interceptor的联系和区别

本文将对拦截器Interceptor进行简单讲解,并通过几个例子对它们的差异进行简要分析。

java拦截器和过滤器有哪些区别

Java拦截器和过滤器有以下区别:1. 执行顺序:过滤器在Servlet容器内部执行,而拦截器在Java代码中执行。过滤器是在请求被发送到Servlet之前或响应被发送到客户端之前执行,而拦截器是在方法调用之前或之后执行。2. 范围:过滤器
2023-10-08

Java拦截器,过滤器,监听器的简单原理和区别

在Java Web开发中,拦截器(Interceptor)、过滤器(Filter)和监听器(Listener)都是为了实现业务的预处理或后处理。拦截器主要用于在处理Controller方法前后添加特定的处理逻辑;过滤器对请求和响应进行预处理和后处理;监听器用于监听和响应Web应用的某些事件。
Java拦截器,过滤器,监听器的简单原理和区别
2023-10-29

java拦截器和过滤器有什么不同

Java拦截器和过滤器在功能和使用场景上有所不同。1. 功能:拦截器主要用于拦截并处理方法调用,可以在方法执行前后进行一些额外的处理,如日志记录、权限验证等。而过滤器主要用于过滤请求和响应,可以在请求到达目标之前或响应返回之前进行一些预处理
2023-10-10

SpringBoot面试突击之过滤器和拦截器区别详解

过滤器(Filter)和拦截器(Interceptor)都是基于 AOP(Aspect Oriented Programming,面向切面编程)思想实现的,用来解决项目中某一类问题的两种“工具”,但二者有着明显的差距,接下来我们一起来看
2022-11-13

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录