拦截器与过滤器的区别(九)

前言

相同之处:

【Spring的拦截器】与【Servlet的Filter】有相似之处,比如二者都是AOP编程思想的体现,都能实现权限检查、日志记录等。

不同之处:

  • 使用范围不同:【Filter是Servlet规范固定的,只能用于Web程序中】,而【拦截器既可以用户Web程序,也可以用于Application、Swing程序中】。
  • 规范不同:Filter是在Servlet规范中定义的,是【Servlet容器支持】的,而拦截器是在Spring容器内的,是【Spring框架支持】的。
  •  使用的资源不同:同其他的代码块一样,拦截器也是一个Spring的组件,归Spring管理,配置在Spring文件中,因此能使用Spring里得任何资源、对象,例如Service对象、数据源、事务管理等,通过Ioc注入道拦截器即可。而Filter则不能。
  • 深度不同:【Filter在只在Servlet启动前后起作用。而拦截器能够深入到方法前后、异常抛出前后等】,因此拦截器的使用弹性更大一些,所以在使用Spring架构的程序中,要优先使用拦截器。

一、二者理解

过滤器(Filter)

过滤器,是在java web中将你传入的request、response提前过滤掉一些信息,或者提前设置一些参数。然后再传入Servlet或Struts2的 action进行业务逻辑处理。比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入Servlet或Struts2的action前统一设置字符集,或者去除掉一些非法字符。

拦截器(Interceptor)

拦截器,是面向切面编程(AOP,Aspect Oriented Program)的。就是在你的Service或者一个方法前调用一个方法,或者在方法后调用一个方法。比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。

通俗理解:
(1)过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。(理解:就是一堆字母中取一个B)
(2)拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。(理解:就是一堆字母中,干预它,通过验证的少点,顺便干点别的东西)

二、拦截器与过滤器的区别

区别:

①:拦截器是基于java的反射机制的,而过滤器是基于函数的回调。
②:拦截器不依赖于servlet容器,而过滤器依赖于servlet容器。
③:拦截器只对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④:拦截器可以访问action上下文、值、栈里面的对象,而过滤器不可以。
⑤:在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥:拦截器可以获取IOC容器中的各个bean,而过滤器不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

三、拦截器与过滤器的触发时机

拦截器与过滤器触发时机不一样

过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。

过滤器包裹servlet,servlet包裹住拦截器。

四、使用场景

4.1拦截器使用场景

SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。

1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;
3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。
5、OpenSessionInView:如hibernate,在进入处理器打开Session,在完成后关闭Session。

4.2何时使用拦截器?何时使用过滤器?

如果是非spring项目,那么拦截器不能用,只能使用过滤器。

如果是处理controller前后,既可以使用拦截器也可以使用过滤器。

如果是处理dispaterServlet前后,只能使用过滤器。

五、图解

1、过滤器和拦截器触发时机不一样,过滤器是在【请求进入容器后,但请求进入servlet之前】进行预处理的。请求结束返回也是,是【在servlet处理完后,返回给前端之前】。

在这里插入图片描述

2、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。而过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。

过滤器拦截器运行先后步骤:


在这里插入图片描述

其中第2步,SpringMVC的机制是由DispaterServlet来分发请求给不同的Controller,其实这一步是在Servlet的service()方法中执行的。

3、过滤器的实现基于回调函数。而【拦截器(代理模式)的实现基于反射】,代理分静态代理和动态代理,动态代理是拦截器的简单实现。


在这里插入图片描述

六、部分代码

6.1、过滤器(Filter)

首先说一下Filter的使用地方,我们在配置web.xml时,总会配置下面一段设置字符编码,不然会导致乱码问题:

<filter>
    <filter-name>encoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>encoding</filter-name>
    <servlet-name>/*</servlet-name>
</filter-mapping>


配置这个地方的目的,是让所有的请求都需要进行字符编码的设置,下面来介绍一下Filter。

(1)过滤器(Filter):它依赖于servlet容器。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的,是用来做一些过滤操作,获取我们想要获取的数据,比如:在Javaweb中,对传入的request、response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者Controller进行业务逻辑操作。通常用的场景是:在过滤器中修改字符编码(CharacterEncodingFilter)、在过滤器中修改HttpServletRequest的一些参数(XSSFilter(自定义过滤器)),如:过滤低俗文字、危险字符等。

6.2、拦截器(Interceptor)

拦截器的配置一般在SpringMVC的配置文件中,使用Interceptors标签,具体配置如下:

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**" />
        <bean class="com.scorpios.atcrowdfunding.web.LoginInterceptor"></bean>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**" />
        <bean class="com.scorpios.atcrowdfunding.web.AuthInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

(2)拦截器(Interceptor):它依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在service或者一个方法前,调用一个方法,或者在方法后,调用一个方法,比如动态代理就是拦截器的简单实现,在调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在调用方法后打印出字符串,甚至在抛出异常的时候做业务逻辑的操作。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。

6.3总结

对于上述过滤器和拦截器的测试,可以得到如下结论:
(1)、Filter需要在web.xml中配置,依赖于Servlet;
(2)、Interceptor需要在SpringMVC中配置,依赖于框架;
(3)、Filter的执行顺序在Interceptor之前,具体的流程见下图;

è¿éåå¾çæè¿°

(4)、两者的本质区别:拦截器(Interceptor)是基于Java的反射机制,而过滤器(Filter)是基于函数回调。从灵活性上说拦截器功能更强大些,Filter能做的事情,都能做,而且可以在请求前,请求后执行,比较灵活。Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录不登录之类),太细的话,还是建议用interceptor。不过还是根据不同情况选择合适的。

参看链接:

https://blog.csdn.net/weixin_44502804/article/details/93139550

https://blog.csdn.net/longzhongxiaoniao/article/details/85727725

https://www.iteye.com/blog/uule-2442198

如果错过太阳时你流了泪,那你也要错过群星了。
在所有的矛盾中,要优先解决主要矛盾,其他矛盾也就迎刃而解。
不要做个笨蛋,为失去的郁郁寡欢,聪明的人,已经找到了解决问题的办法,或正在寻找。
原文地址:https://www.cnblogs.com/szrs/p/14404357.html