一 简介

(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:

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 TestFilter1 extends OncePerRequestFilter { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
//在DispatcherServlet之前执行
system.out.println("############TestFilter1 doFilterInternal executed############");
filterChain.doFilter(request, response);
//在视图页面返回给客户端之前执行,但是执行顺序在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############"); } }

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的配置文件中注册这两个拦截器:

<!-- 拦截器 -->
<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>

SpringMVC的拦截器和过滤器的区别的更多相关文章

  1. Java Web 拦截器和过滤器的区别

    一.AOP:面向切面编程,Java Web中有两个常用的技术:拦截器.过滤器 二.拦截器 1.定义:在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作 2.原理:大部分时候,拦截器方法都 ...

  2. Struts2拦截器和过滤器的区别?

    ①过滤器依赖于Servlet容器,而拦截器不依赖于Servlet容器. ②Struts2 拦截器只能对Action请求起作用,而过滤器则可以对几乎所 有请求起作用. ③拦截器可以访问 Action上下 ...

  3. 面试题:struts 拦截器和过滤器

    拦截器和过滤器的区别 过滤器是servlet规范中的一部分,任何java web工程都可以使用. 拦截器是struts2框架自己的,只有使用了struts2框架的工程才能用. 过滤器在url-patt ...

  4. Spring拦截器和过滤器

    什么是拦截器 拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在方法执行之前或之后加入某些操作,其实就是AOP的一种实现策略.它通过动态拦截Action调用的对象,允许开发者 ...

  5. springMVC拦截器和过滤器总结

    拦截器: 用来对访问的url进行拦截处理 用处: 权限验证,乱码设置等 spring-mvc.xml文件中的配置: <beans xmlns="http://www.springfra ...

  6. java 拦截器和过滤器区别(转载)

    1.拦截器是基于java的反射机制的,而过滤器是基于函数回调 2.过滤器依赖与servlet容器,而拦截器不依赖与servlet容器 3.拦截器只能对action请求起作用,而过滤器则可以对几乎所有的 ...

  7. SpringMVC学习笔记:拦截器和过滤器

    首先说明一下二者的区别: 1. 拦截器基于java的反射机制,而过滤器是基于函数回调 2. 拦截器不依赖于servlet容器,过滤器依赖servlet容器 3. 拦截器只能对action请求起作用,而 ...

  8. struts2拦截器和过滤器区别

    1.拦截器是基于java反射机制的,而过滤器是基于函数回调的.2.过滤器依赖于servlet容器,而拦截器不依赖于servlet容器.3.拦截器只能对Action请求起作用,而过滤器则可以对几乎所有请 ...

  9. Spring Boot2(七):拦截器和过滤器

    一.前言 过滤器和拦截器两者都具有AOP的切面思想,关于aop切面,可以看上一篇文章.过滤器filter和拦截器interceptor都属于面向切面编程的具体实现. 二.过滤器 过滤器工作原理 从上图 ...

随机推荐

  1. C语言:文件

    文件是数据源的一种,最主要的作用是保存数据.在操作系统中,为了统一对各种硬件的操作,简化接口,不同的硬件设备也都被看成一个文件.对这些文件的操作,等同于对磁盘上普通文件的操作.例如: 通常把显示器称为 ...

  2. RPC远程协议之Thrift入门

    在上一篇文章<RPC远程协议之原理分析>中,我介绍了RPC的工作原理及欲实现RPC框架功能应该做哪些事情,因为要做的事情太多,完全由开发人员研发实现,不是很现实,所以市面上出现了诸多RPC ...

  3. sql-5-事务,索引

    事务 1.ACID概念 原子性(Atomicity) 要么都成功,要么都失败 一致性(consistency) 事务前后的数据完整性保持一致 持久性(Durability) 事务一旦提交则不可逆,持久 ...

  4. Java-数组有关

    1.复制数组 复制数组主要有三类方法: 1.使用循环语句逐个赋值数组元素 2.使用System类中的静态方法arraycopy 3.使用clone方法复制数组 对于2,详述如下: arraycopy( ...

  5. 【Uva11400 Lighting System Design】动态规划

    分析 先按照电压从小到大排序,做一下前缀和s[i]求i之前的电灯泡的数量. 状态:$ F_i\(表示到\) i$个灯泡的最小开销. 状态转移方程:$ F_i=F_j+(s[i]-s[j])\times ...

  6. Allure测试框架 python

    关于Allure Allure是一个report框架,可以基于一些测试框架生成测试报告,比较常用的一般是Junit/Testng框架: Allure 生成的报告样式简洁美观,同时又支持中文: Allu ...

  7. 货币兑换问题(动态规划法)——Python实现

      # 动态规划法求解货币兑换问题 # 货币系统有 n 种硬币,面值为 v1,v2,v3...vn,其中 v1=1,使用总值为money的钱与之兑换,求如何使硬币的数目最少,即 x1,x2,x3... ...

  8. 在 CentOS 7.5 64位上使用 yum 安装 MySQL 8.0

    前段时间在 CentOS 7.5 64位上安装 MySQL 8.0.查了些资料,在这里记录一下详细的安装和设置步骤. 一.安装 使用yum安装MySQL之前需要先下载对应的.rpm文件,下载方法: 去 ...

  9. 高德开放平台实现批量自定义marker和信息窗体显示

    上篇博客提到云图无法实现文本标签标记marker,这篇博客着重实现在marker点文本标记以及自定义按钮窗体显示. 1.效果: 2.代码实现 <!doctype html> <htm ...

  10. SQL SERVER 作业问题(SET 选项的设置不正确: 'QUOTED_IDENTIFIER'。),以及其它定时sql执行方式探索

    在实时曲线测试平台中,需要用到实时测试数据作为依据,评估程序的可靠性.在编写sql server作业时,出现了一些问题,经过研究给予解决,供大家参考. 1.编写脚本如下: declare @i int ...