SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系
摘自: http://blog.csdn.net/xiaoyaotan_111/article/details/53817918
一 简介
(1)过滤器:
依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等
关于过滤器的一些用法可以参考我写过的这些文章:
继承HttpServletRequestWrapper以实现在Filter中修改HttpServletRequest的参数:https://www.zifangsky.cn/677.html
在SpringMVC中使用过滤器(Filter)过滤容易引发XSS的危险字符:https://www.zifangsky.cn/683.html
(2)拦截器:
依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理
关于过滤器的一些用法可以参考我写过的这些文章:
在SpringMVC中使用拦截器(interceptor)拦截CSRF攻击(修):https://www.zifangsky.cn/671.html
SpringMVC中使用Interceptor+cookie实现在一定天数之内自动登录:https://www.zifangsky.cn/700.html
二 多个过滤器与拦截器的代码执行顺序
如果在一个项目中仅仅只有一个拦截器或者过滤器,那么我相信相对来说理解起来是比较容易的。但是我们是否思考过:如果一个项目中有多个拦截器或者过滤器,那么它们的执行顺序应该是什么样的?或者再复杂点,一个项目中既有多个拦截器,又有多个过滤器,这时它们的执行顺序又是什么样的呢?
下面我将用简单的代码来测试说明:
(1)先定义两个过滤器:
i)过滤器1:
- <a target="_blank" href="http://www.07net01.com/tags-package-0.html" class="infotextkey" style="background:transparent; color:rgb(66,139,202)">package</a> cn.zifangsky.filter;
- import java.io.IOException;
- import javax.servlet.FilterChain;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.web.filter.OncePerRequestFilter;
- public class TestFilter1 extends OncePerRequestFilter {
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
- throws ServletException, IOException {
- //在DispatcherServlet之前执行
- <a target="_blank" href="http://www.07net01.com/tags-system-0.html" class="infotextkey" style="background:transparent; color:rgb(66,139,202)">system</a>.out.println("############TestFilter1 doFilterInternal executed############");
- filterChain.doFilter(request, response);
- //在视图页面返回给<a target="_blank" href="http://www.07net01.com/tags-%E5%AE%A2%E6%88%B7%E7%AB%AF-0.html" class="infotextkey" style="background:transparent; color:rgb(66,139,202)">客户端</a>之前执行,但是执行顺序在Interceptor之后
- System.out.println("############TestFilter1 doFilter after############");
- // try {
- // Thread.sleep(10000);
- // } catch (InterruptedException e) {
- // e.printStackTrace();
- // }
- }
- }
ii)过滤器2:
- package cn.zifangsky.filter;
- import java.io.IOException;
- import javax.servlet.FilterChain;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.web.filter.OncePerRequestFilter;
- public class TestFilter2 extends OncePerRequestFilter {
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
- throws ServletException, IOException {
- System.out.println("############TestFilter2 doFilterInternal executed############");
- filterChain.doFilter(request, response);
- System.out.println("############TestFilter2 doFilter after############");
- }
- }
iii)在web.xml中注册这两个过滤器:
- <!-- 自定义过滤器:testFilter1 -->
- <filter>
- <filter-name>testFilter1</filter-name>
- <filter-class>cn.zifangsky.filter.TestFilter1</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>testFilter1</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <!-- 自定义过滤器:testFilter2 -->
- <filter>
- <filter-name>testFilter2</filter-name>
- <filter-class>cn.zifangsky.filter.TestFilter2</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>testFilter2</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
(2)再定义两个拦截器:
i)拦截器1,基本拦截器:
- package cn.zifangsky.interceptor;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
- public class BaseInterceptor implements HandlerInterceptor{
- /**
- * 在DispatcherServlet之前执行
- * */
- public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
- System.out.println("************BaseInterceptor preHandle executed**********");
- return true;
- }
- /**
- * 在controller执行之后的DispatcherServlet之后执行
- * */
- public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
- throws Exception {
- System.out.println("************BaseInterceptor postHandle executed**********");
- }
- /**
- * 在页面渲染完成返回给客户端之前执行
- * */
- public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
- throws Exception {
- System.out.println("************BaseInterceptor afterCompletion executed**********");
- // Thread.sleep(10000);
- }
- }
ii)指定controller请求的拦截器:
- package cn.zifangsky.interceptor;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
- public class TestInterceptor implements HandlerInterceptor {
- public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
- System.out.println("************TestInterceptor preHandle executed**********");
- return true;
- }
- public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
- throws Exception {
- System.out.println("************TestInterceptor postHandle executed**********");
- }
- public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
- throws Exception {
- System.out.println("************TestInterceptor afterCompletion executed**********");
- }
- }
iii)在SpringMVC的配置文件中注册这两个拦截器:
- <!-- 拦截器 -->
- nbsp; <mvc:interceptors>
- <!-- 对所有请求都拦截,公共拦截器可以有多个 -->
- <bean name="baseInterceptor" class="cn.zifangsky.interceptor.BaseInterceptor" />
- <!-- <bean name="testInterceptor" class="cn.zifangsky.interceptor.TestInterceptor" /> -->
- <mvc:interceptor>
- <!-- 对/test.html进行拦截 -->
- <mvc:mapping path="/test.html"/>
- <!-- 特定请求的拦截器只能有一个 -->
- <bean class="cn.zifangsky.interceptor.TestInterceptor" />
- </mvc:interceptor>
- </mvc:interceptors>
(3)定义一个测试使用的controller:
- package cn.zifangsky.controller;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.servlet.ModelAndView;
- @Controller
- public class TestController {
- @RequestMapping("/test.html")
- public ModelAndView handleRequest(){
- System.out.println("---------TestController executed--------");
- return new ModelAndView("test");
- }
- }
(4)视图页面test.jsp:
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
- %>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <base href="http://983836259.blog.51cto.com/7311475/">
- <title>FilterDemo</title>
- </head>
- <body>
- <%
- System.out.println("test.jsp is loading");
- %>
- <div align="center">
- This is test page
- </div>
- </body>
- </html>
(5)测试效果:
启动此测试项目,可以看到控制台中输出如下:

这就说明了过滤器的运行是依赖于servlet容器的,跟springmvc等框架并没有关系。并且,多个过滤器的执行顺序跟xml文件中定义的先后关系有关
接着清空控制台中的输出内容并访问:http://localhost:9180/FilterDemo/test.html
可以看到,此时的控制台输出结果如下:

相信从这个打印输出,大家就可以很清晰地看到有多个拦截器和过滤器存在时的整个执行顺序了。当然,对于过个拦截器它们之间的执行顺序跟在SpringMVC的配置文件中定义的先后顺序有关
注:对于整个SpringMVC的执行流程来说,如果加上上面的拦截器和过滤器,其最终的执行流程就如下图所示:

- 顶
- 7
- 踩
- 0
SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系的更多相关文章
- 拦截器Interceptor和过滤器Filter的区别
(1)过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西.定义这些要求的工具,就是过滤器.(理解:就是一堆字母中取一个B) (2)拦截器(Interceptor):在一个 ...
- SSM-SpringMVC-33:SpringMVC中拦截器Interceptor讲解
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 拦截器Interceptor: 对处理方法进行双向的拦截,可以对其做日志记录等 我选择的是实现Handler ...
- Java过滤器(Filter)与SpringMVC拦截器(Interceptor)之间的关系与区别
过滤器和拦截器的区别: ①拦截器是基于java的反射机制的,而过滤器是基于函数回调. ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器. ③拦截器只能对action请求起作用,而过滤 ...
- struts2的拦截器(Interceptor)与过滤器(Filter)
一.拦截器与过滤器的区别: 1.filter基于回调函数,我们需要实现的filter接口中doFilter方法就是回调函数,而interceptor则基于Java本身的反射机制,这是两者最本质的区别. ...
- SpringMVC处理器拦截器 Interceptor
拦截器概念 Java 里的拦截器是动态拦截action调用的对象.它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种 ...
- java 过滤器(Filter)与springMVC 拦截器(interceptor)的实现案例
java 过滤器Filter: package com.sun.test.aircraft.filter;import javax.servlet.*;import java.io.IOExcepti ...
- 过滤器(Filter)和拦截器(Interceptor)
过滤器(Filter) Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序.它依赖于servlet容器,在实现上,基于函数回调,它可以对几乎所有请求 ...
- 二十五、过滤器Filter,监听器Listener,拦截器Interceptor的区别
1.Servlet:运行在服务器上可以动态生成web页面.servlet的声明周期从被装入到web服务器内存,到服务器关闭结束.一般启动web服务器时会加载servelt的实例进行装入,然后初始化工作 ...
- Spring filter和拦截器(Interceptor)的区别和执行顺序
转载自:http://listenup.iteye.com/blog/1559553 1.Filter过滤器只过滤jsp文件不过滤action请求解决方案 解决办法:在web.xml中将filter的 ...
- Java 中的过滤器Filter 和拦截器 Interceptor
1.先说拦截器 Interceptor 本项目以springboot为例: 新建 InterceptorConfig package com.opendev.mystudy.MyInterceptor ...
随机推荐
- Codeforces Gym100187C Very Spacious Office 贪心 堆
原文链接https://www.cnblogs.com/zhouzhendong/p/CF-Gym100187C.html 题目传送门 - CF-Gym100187C 题意 给定 $n$ 个房间以及 ...
- 空间分析工具:GIS
1.数据空间 数据空间是指用来表示空间实体的的位置.几何特征及其属性特征的数据. 位置:经纬度.地址.相对位置: 几何特征:点.线.面.形状: 属性特征:面积.周长.人口.经济等属性. POI数据.O ...
- 011 Linux环境下配置eclipse,以及创建maven工程
一:maven的安装 1.安装配置maven环境变量 2.验证 二:eclipse的安装 3.解压配置eclipse 4.启动eclipse,必须在虚拟机的eclipse下启动 5.结果 三:修改配置 ...
- QT5版本添加icon图标步骤
QT5版本添加icon图标方法收藏 方法1: step1: 把要显示的图标文件,比如为1.ico文件放到工程v的根目录下 step2: 修改当前项目XXX.pro文件,在文件末尾添加如下内容(注意=的 ...
- POJ 1988 Cube Stacking 【带权并查集】
<题目链接> 题目大意: 有几个stack,初始里面有一个cube.支持两种操作: 1.move x y: 将x所在的stack移动到y所在stack的顶部. 2.count x:数在x所 ...
- HDU 3415 Max Sum of Max-K-sub-sequence【单调队列】
<题目链接> 题目大意: 给你一段从1~N的圆形序列,要你求出这段圆形序列中长度不超过K的最大连续子序列之和是多少,并且输出这子序列的起点和终点. 解题分析: 既然是求连续子序列之和,我们 ...
- ACM10.14题解
ACM10.14题解 第一次打周赛,感觉还是比较紧张的,应该开完所有的题再做,而不是硬做,没必要硬杠英语,还是不要抱有侥幸心理,做对一定是完全理解且会,自己小心边界问题,不要瞎交. A:暴力明显不对嘛 ...
- soul
mark,数据使用gzip加密,因为公司网络卡,明天后天看.
- centos6.5安装/升级到python2.7
https://www.cnblogs.com/harrymore/p/9024287.html
- docker eureka 注册中心 服务提供者通信机制
docker run -d --name gateway9527 -p 9527:9527 --add-host=eureka7001.com:192.168.1.15 -v /var/jen ...