过滤器和拦截器

  • 过滤器
    • Servlet 过滤器是
    • Servlet 过滤器体系结构
    • 过滤器的实现步骤
      • 第一步 一个过滤器类实现
        • 要过滤的servlet类随便写一个
        • 过滤器类
      • 第二步配置文件webxml
  • 拦截器
    • 拦截器的方法
    • 写一个拦截器步骤
  • 过滤器和拦截器的区别

过滤器

  Servlet 过滤器是小型的 Web 组件,它们拦截请求和响应,以便查看、提取或以某种方式操作正在客户机和服务器之间交换的数据。过滤器是通常封装了一些功能的 Web 组件,这些功能虽然很重要,但是对于处理客户机请求或发送响应来说不是决定性的。

  典型的例子包括记录关于请求和响应的数据、处理安全协议、管理会话属性, 等等。过滤器提供一种面向对象的模块化机制,用以将公共任务封装到可插入的组件中,这些组件通过一个配置文件来声明,并动态地处理。

  过滤器提供一种面向对象的模块化机制,用以将公共任务封装到可插入的组件中,这些组件通过一个配置文件来声明,并动态地处理。

Servlet 过滤器是

  •   声明式的:过滤器通过 Web 部署描述符(web.xml)中的 XML 标签来声明。这样允许添加和删除过滤器,而无需改动任何应用程序代码或 JSP 页面。
  •   动态的:过滤器在运行时由 Servlet 容器调用来拦截和处理请求和响应。
  •   灵活的:过滤器在 Web 处理环境中的应用很广泛,涵盖诸如日志记录和安全等许多最公共的辅助任务。过滤器还是灵活的,因为它们可用于对来自客户机的直接调用执行预处理和后期处 理,以及处理在防火墙之后的 Web 组件之间调度的请求。最后,可以将过滤器链接起来以提供必需的功能。
  •   模块化的:通过把应用程序处理逻辑封装到单个类文件中,过滤器从而定义了可容易地从请求/响应链中添加或删除的模块化单元。
  •   可移植的:与 Java 平台的其他许多方面一样,Servlet 过滤器是跨平台和跨容器可移植的,从而进一步支持了 Servler 过滤器的模块化和可重用本质。
  •   可重用的:归功于过滤器实现类的模块化设计,以及声明式的过滤器配置方式,过滤器可以容易地跨越不同的项目和应用程序使用。
  •   透明的:在请求/响应链中包括过滤器,这种设计是为了补充(而不是以任何方式替代)servlet 或 JSP 页面提供的核心处理。因而,过滤器可以根据需要添加或删除,而不会破坏 servlet 或 JSP 页面。

      所以 Servlet 过滤器是通过一个配置文件来灵活声明的模块化可重用组件。

Servlet 过滤器体系结构

  Servlet 过滤器 用于拦截传入的请求和/或传出的响应,并监视、修改或以某种方式处理正在通过的数据流。过滤器是自包含、模块化的组件,可以将它们添加到请求/响应链中, 或者在无需影响应用程序中其他 Web 组件的情况下删除它们。

  过滤器 API 包含 3 个简单的接口,它们整洁地嵌套在 javax.servlet 包中。那 3 个接口分别是 FilterFilterChain FilterConfig

  从编程的角度看,过滤器类将实现 Filter 接口,然后使用这个过滤器类中的 FilterChain 和 FilterConfig 接口。该过滤器类的一个引用将传递给 FilterChain 对象,以允许过滤器把控制权传递给链中的下一个资源。FilterConfig 对象将由容器提供给过滤器,以允许访问该过滤器的初始化数据。

  过滤器三个方法,以便完全实现 Filter 接口

方法名 说明
init() 这个方法在容器实例化过滤器时被调用,它主要设计用于使过滤器为处理做准备。该方法接受一个 FilterConfig 类型的对象作为输入。
doFilter() 与 servlet 拥有一个 service() 方法(这个方法又调用 doPost() 或者 doGet())来处理请求一样,过滤器拥有单个用于处理请求和响应的方法——doFilter()。这个方法接受三个输入参数:一个 ServletRequest、response 和一个 FilterChain 对象。
destroy() 这个方法执行任何清理操作,这些操作可能需要在自动垃圾收集之前进行。展示了一个非常简单的过滤器,它跟踪满足一个客户机的 Web 请求所花的大致时间。

过滤器的实现步骤

第一步 一个过滤器类实现

要过滤的servlet类(随便写一个)

public class DemoServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        System.out.println("demo");
    }

}

过滤器类

public class FirstFilter implements Filter {
    // 当服务器启动时会初始化filter调用此方法
    public void init(FilterConfig arg0) throws ServletException {
        System.out.println("初始化firstfilter");
//获取在配置文件中预置的值
        System.out.println(cfg.getInitParameter("city"));
    }
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        System.out.println(req);
        System.out.println(res);
        System.out.println("第一个过滤器A");
//      让请求继续向下执行
//      若没调用此方法,则请求中断
        chain.doFilter(req, res);
        System.out.println("第一个过滤器B");
    }
    // 当服务器关闭时会销毁filter
    // 会自动调用此销毁方法
    public void destroy() {
        System.out.println("销毁firstfilter");

    }

}

把类名改写,在写一个,可以测试有多个过滤器,程序是怎样实行的。

第二步配置文件web.xml

<filter>
    <filter-name>first</filter-name>
    <filter-class>web.FirstFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>first</filter-name>
    <!-- 该Filter可以过滤/拦截的网络路径 -->
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <filter>
    <filter-name>second</filter-name>
    <filter-class>web.SecondFilter</filter-class>
    <!-- 给此Filter预置数据,在服务器启动时,
        FilterConfig会自动读取该数据,并由
        服务器自动将config对象传入该Filter的init()。 -->
    <init-param>
        <param-name>city</param-name>
        <param-value>北京</param-value>
    </init-param>
  </filter>
  <!-- 多个Filter之间的调用顺序以mapping为准 -->
  <filter-mapping>
    <filter-name>second</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
 <!-- 配置监听器
        1.服务器启动时自动实例化监听器;
        2.在监听目标发生对应事件时(创建销毁)
        服务器会自动调用该监听器的方法
   -->
 <listener>
    <listener-class>web.MyListener</listener-class>
  </listener>

有上面的代码分析知道
有过滤器时代码的执行过程

  • 第一步:当容器第一次加载该过滤器时,init() 方法将被调用。
  • 第二步:过滤(即执行doFilter())
    过滤器的大多数时间都消耗在这里。doFilter() 方法被容器调用,同时传入分别指向这个请求/响应链中的 ServletRequest、ServletResponse 和 FilterChain 对象的引用。然后过滤器就有机会处理请求,将处理任务传递给链中的下一个资源(通过调用 FilterChain 对象引用上的 doFilter()方法,若没调用此方法,则请求中断),之后在处理控制权返回该过滤器时处理响应。
  • 第三步:当服务器关闭时会销毁filter,会自动调用此销毁方法。

有多个过滤器时
 假如有两个过滤器:
  先输出第一个过滤器doFilter()前的结果,然后输出第二个过滤器的doFilter()前的结果,在输出第二个过滤器doFilter()后的结果,最后输出第一个过滤器doFilter()后的结果。
这个输出顺序类似堆栈,先进后出。

拦截器

  是springmvc提供的一个组件,前端控制器会先调用拦截器 ,然后再调用处理器。
  依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理

拦截器的方法:

方法 说明
preHandle() 前端控制器先调用拦截器的preHandle方法, 再调用处理器的处理方法。如果该方法的返回值为true,表示 继续向后调用。
postHandle() 处理器的方法已经执行完毕,在将ModelAndView 返回给前端控制器之前执行该方法。所以,可以在该方法里面修改 ModelAndView。
afterCompletion() 最后执行的方法。

写一个拦截器步骤

  第一步:写一个java类,实现HandlerInterceptor接口。
  第二步:将拦截处理逻辑写在对应的方法里。
  第三步:配置拦截器(spring配置文件)。

public class SomeInterceptor implements HandlerInterceptor{
    /**
     * 前端控制器先调用拦截器的preHandle方法,再调用处理器的处理方法。
        arg2:处理器方法对象。
        如果返回值为true,表示继续向后调用;
        如果返回值为false,不会继续向后调用,
        请求处理完毕。
     */
    public boolean preHandle(
            HttpServletRequest req,
            HttpServletResponse res,
            Object arg2) throws Exception {
        System.out.println("SomeInterceptor's preHandle()");
        return true;
    }

    /**
     * 处理器的方法已经执行完毕,在将ModelAndView返回给前端控制器之前执行该方法。
     * 所以,可以在该方法里面修改ModelAndView。
     */
    public void postHandle(
            HttpServletRequest req,
            HttpServletResponse res,
            Object arg2, ModelAndView mav)
            throws Exception {
        System.out.println("SomeInterceptor's "+ "postHandle()");
    }

    /**
     * 最后执行的方法。
     * ex:处理器抛出的异常对象。
     */
    public void afterCompletion(
            HttpServletRequest req,
            HttpServletResponse res,
            Object arg2, Exception ex)
            throws Exception {
        System.out.println("SomeInterceptor's "+ "afterCompletion()");
    }

}

配置spring配置文件

<!-- 配置拦截器
        可以在interceptors下面配置多个拦截器,
        拦截器的执行的先后顺序由配置的先后顺序来决定。
        注意:
            如果要拦截多层路径,比如"/abc/hello2.do",
            应该使用 /**。
      -->

     <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="interceptors.SomeInterceptor"/>
        </mvc:interceptor>
     </mvc:interceptors>

   注意的细节都在代码张有注释,可以看下。

过滤器和拦截器的区别:

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

从另一个角度说
  ①使用范围不同 Filter 是Servlet 规定的.只能用于web 程序.而拦截器既可以用于Web 程序,也可以用于Apllicatioon,Swing程序中。
  ②规范不同:Filter是在SerVlet 规范定义的,是Servlet容器支持的。而拦截器是在Spring 容器内的,Spring 框架所支持的。
  ③使用资源不同:同其他代码块一样,拦截器也是一个Spring的组件,归Spring 管理。配置在Spring 中,因此能使用Spring 中的任何资源,对象,例如Service对象,数据源,事务管理等。通过Ioc注入到拦截器即可。而filter 则不能。
  ④深度不同:Filter 只在Servlet前后起作用,而拦截器能深入到方法前后,异常抛出前后因而拦截器的使用具有更大的弹性,所以在spring 中优先使用拦截器。

  过滤器: 依赖于servlet容器,使用回调函数,过滤范围大

  拦截器: 依赖于框架容器 比如spring、mybatis ,灵活
总之到底用哪个要看情况而定,希望我写的这些对大家有用,有用的话就请大家关注下我,或者点个赞。

时间: 2025-01-24 05:24:43

过滤器和拦截器的相关文章

ssh-SSH框架中的过滤器,拦截器,监听器的作用和执行顺序

问题描述 SSH框架中的过滤器,拦截器,监听器的作用和执行顺序 如题,网上搜了一些资料看了一下,还不是很清楚,求各位大神指导 解决方案 http://www.cnblogs.com/tonyY/p/5168836.html 解决方案二: 首先,过滤器是在请求到达Server端之前执行的,或者响应结果到达客户端之前.功能是在服务器和客户端中间增加了一个中间层(类似于外观模式中间也是加了一层~~),可以对两者之间的交互进行统一的处理,每一个客户端提交的请求都需要通过过滤器的处理, 然后再进行其他的操

JavaWeb过滤器的运行机制理解及过滤器.监听器.拦截器-原理&amp;区别

过滤器Filter 一.过滤器的概念. Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能.例如实现URL级别的权限访问控制.过滤敏感词汇.压缩响应信息等一些高级功能. 二.过滤器的运行机制.   没有加Filter的web项目运行机制如下:   加上Filter的web运行机制: 由此可见:Filter的作用

struts2过滤器和拦截器的区别分析_java

本文分析了struts2过滤器和拦截器的区别.分享给大家供大家参考,具体如下: 一.本质区别: 1. 拦截器是基于java的反射机制的,而过滤器是基于函数回调. 2. 拦截器不依赖与servlet容器,过滤器依赖与servlet容器. 3. 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用. 4. 拦截器可以访问action上下文.值栈里的对象,而过滤器不能访问. 5. 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次 二.使用区别:

Java Web 中 过滤器与拦截器的区别

过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符 拦截器,是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现

过滤器和拦截器异同

 过滤器 package com.xy.filter; 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

过滤器 拦截器 controller 页面 的执行顺序

经过本人的最后测试得出的结论是 由于最近做的项目中有一部分是接口远程调用,用到了接入权限和业务权限的鉴定,需要采用SpringMVC的拦截器,以前用Struts2的时候用过拦截器,而SpringMVC的拦截器功能之前没研究过,所以这次来稍微研究一下,得出的结论是SpringMVC的拦截器和Struts2的拦截器原理几乎是一模一样的,都是利用反射功能实现动态代理. 因为过滤器和拦截器有很多相似甚至相同的地方,因为很多时候二者都能达到相同的能力.所以也重新看了下过滤器. 过滤器和拦截器的区别,百度了

Servlet,过滤器,监听器,拦截器的区别

由于最近两个月工作比较清闲,个人也比较"上进",利用工作空余时间,也继续学习了一下,某天突然想起struts2和struts1的区别的时 候,发现为什么struts1要用servlet,而struts2要用filter呢?一时又发现,servlet和filter有什么区别呢?于是看 了看web.xml,一时又发现,咦,servlet.filter.listener?还有个interceptor?对于这几个概念,本应是初学者就 掌握的东东了,可惜本人基础学的不好,只能是现在补课.于是就有

JavaWeb中Struts2拦截器深入分析(一)_java

一.struts2中的拦截器(框架功能核心) 1.过滤器VS拦截器 过滤器VS拦截器功能是一回事.过滤器是Servlet规范中的技术,可以对请求和响应进行过滤. 拦截器是Struts2框架中的技术,实现AOP(面向切面)的编程思想,是可插拔的, 可以对访问某个 Action 方法之前或之后实施拦截. 拦截器栈(Interceptor Stack): 将拦截器按一定的顺序联结成一条链. 在访问被拦截的方法时, Struts2拦截器链中的拦截器就会按其之前定义的顺序被依次调用 Struts2执行原理

字符编码拦截器/过滤器无效的原因

  有时候配置了拦截器或者过滤器,来将字符设置为UTF-8,但是有时候我们表单提交,发现提交到数据库的时候还是乱码,这是为毛?   拦截器或者过滤器对表单只是对表单的post方式有效!   如果表单是get方式的话,需要在tomcat里面加东西才能起作用.   所以尽量用post方式吧.