java中拦截器和过滤器详解

article/2025/8/26 3:34:25

1 过滤器和拦截器的异同

1.1 一张图表明两者之间的差异:

tomcat,filter,servet,interceptor以及controller等各种容器的关系图

https://pic3.zhimg.com/v2-da6aae17a961060915487d27e10d1d5a_r.jpg

1.2 两者的区别:

  • 拦截器是基于java的反射机制的,而过滤器是基于函数回调。

  • 拦截器不依赖与servlet容是依赖于spring容器,过滤器依赖与servlet容器。

  • 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用,可以限制用户对图片,文件以及其他资源的访问。

  • 拦截器可以访问action请求上下文、值栈里的对象,而过滤器不能访问。

  • 在action的生命周期中,拦截器可以多次被调用(因为拦截器是基于反射机制实现的,即通过加载java字节码而实现的函数的调用,所以每一次运行拦截器的时候都需要找到拦截器相关的字节码并且执行),而过滤器只需在容器初始化时被调用一次(意思是只需要调用一次,filter过滤器程序就会一直在内存中执行下去,每当碰到一次请求,服务器无需再次调用都会进行拦截,除非被主动摧毁。(1)启动服务器时加载过滤器的实例,并调用init()方法来初始化实例;(2)、每一次请求时都只调用方法doFilter()进行处理;(3)、停止服务器时调用destroy()方法,销毁实例。)。

  • 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

1.3 两者的相同之处:

本文主要对基于Spring boot对过滤器和拦截器的配置进行的讲解。无论是过滤器还是拦截器都属于AOP(面向切面编程)思想的具体实现。

2 过滤器

2.1 用法

当Web容器接受到一个对资源的请求时:

  1. 它将判断是否有过滤器与这个资源相关联。
  2. 如果有,那么容器将把请求交给过滤器进行处理。在过滤器中,你可以改变请求的内容,或者重新设置请求的报头信息,然后再将请求发送给目标资源
  3. 当目标资源对请求作出响应时候,容器同样会将响应先转发给相应的过滤器。

2.2 作用

在过滤器中你可以对响应的内容进行转换,然后再将响应发送到客户端。常见的过滤器用途

主要包括:

  • 对用户请求进行统一认证
  • 对用户的访问请求进行记录和审核、
  • 对用户发送的文本数据进行过滤或替换,比如替换掉脏话、
  • 转换图象格式、
  • 对响应内容进行压缩以减少传输量、
  • 对请求或响应进行加解密处理、
  • 触发资源访问事件、
  • 对XML的输出应用XSLT等。

2.3 实现过滤器 方法一:不使用@WebFilter下,既需要编写过滤器类,又要编写配置类

2.3.1 先编写过滤器类

过滤器类就是指 当拦截到某一个请求后,在该请求发往servlet容器前,执行什么操作,需要进行什么处理

public class LogCostFilter implements Filter{@Overridepublic void init(FilterConfig filterConfig)throws ServletException{}@Overridepublic void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain)throws IOException,ServletException{long start =System.currentTimeMillis();filterChain.doFilter(servletRequest,servletResponse);System.out.println("Execute cost="+(System.currentTimeMillis()-start));}@Overridepublic void destroy(){}
}

这段代码的逻辑比较简单,就是在方法执行前先记录时间戳,然后通过过滤器链完成请求的执行,在返回结果之间计算执行的时间。这里需要主要,这个类必须继承Filter类,这个是Servlet的规范,这个跟以前的Web项目没区别。

2.3.2 再在其配置类中配置过滤器需要拦截的请求类型的正则表达式以及决定使用哪一个过滤器类

但是,有了过滤器类以后,以前的web项目可以在web.xml中进行配置,但是spring- boot项目并没有web.xml这个文件,那怎么配置?在Spring boot中,我们需要FilterRegistrationBean来完成配置。其实现过程如下:


@Configuration
public class FilterConfig{@Beanpublic FilterRegistrationBean registFilter(){FilterRegistrationBean registration =new FilterRegistrationBean();registration.setFilter(newLogCostFilter());registration.addUrlPatterns("/*");registration.setName("LogCostFilter");registration.setOrder(1);return registration;}
}

这样配置就完成了,需要配置的选项主要包括实例化Filter类,然后指定url的匹配模式,设置过滤器名称和执行顺序,这个过程和在web.xml中配置其实没什么区别,只是形式不同而已。现在我们可以启动服务器访问任意URL:

https://pic4.zhimg.com/80/v2-5bdb90fc22e1c4f8ae175e7d80721187_1440w.jpg

2.4 过滤器实现代码 方法二:仅仅使用@WebFilter和过滤器类,不要编写配置类

大家可以看到上面的配置已经生效了。除了通过 FilterRegistrationBean 来配置以外,还有一种更直接的办法,

2.4.1 直接通过注解@WebFilter就可以完成了:

@WebFilter(urlPatterns ="/*", filterName ="logFilter2")
public class LogCostFilter2 implements Filter{@Overridepublicvoid init(FilterConfig filterConfig)throwsServletException{}@Overridepublic void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain)throwsIOException,ServletException{long start =System.currentTimeMillis();filterChain.doFilter(servletRequest, servletResponse);System.out.println("LogFilter2 Execute cost="+(System.currentTimeMillis()- start));}@Overridepublic void destroy(){}
}

2.4.2

这里直接用@WebFilter就可以进行配置,同样,可以设置url匹配模式,过滤器名称等。这里需要注意一点的是@WebFilter这个注解是Servlet3.0的规范,并不是Spring boot提供的。除了这个注解以外,我们还需在配置类中加另外一个注解:@ServletComponetScan,指定扫描的包。

@SpringBootApplication
@MapperScan("com.pandy.blog.dao")
@ServletComponentScan("com.pandy.blog.filters")
public class springbootApplication{public static void main(String[] args) throws Exception{SpringApplication.run(Application.class, args);}
}

现在,我们再来访问一下任意URL:

https://pic1.zhimg.com/80/v2-7c9f6498a097504593fa6bb708961c80_1440w.jpg

2.4.3 多个拦截器存在时候的执行顺序问题

可以看到,我们配置的两个过滤器都生效了。细心的读者会发现,第二个Filter我们并没有指定执行的顺序,但是却在第一个Filter之前执行。这里需要解释一下,@WebFilter这个注解并没有指定执行顺序的属性,其执行顺序依赖于Filter的名称,是根据Filter类名(注意不是配置的filter的名字)的字母顺序倒序排列,并且@WebFilter指定的过滤器优先级都高于FilterRegistrationBean配置的过滤器。有兴趣的朋友可以自己实验一下。

3 拦截器

3.1 拦截器定义

3.1.1 讲一讲拦截器实现的机制。

在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截,然后在之前或之后加上某些操作。拦截是AOP的一种实现策略。

3.1.2 拦截器作用有什么作用呢?

AOP面向切面有什么作用,那么拦截器就有什么作用。

  • 日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV…
  • 权限检查:认证或者授权等检查性能
  • 监控:通过拦截器在进入处理器之前记录开始时间,处理完成后记录结束时间,得到请求处理时间。
  • 通用行为:读取cookie得到用户信息并将用户对象放入请求头中,从而方便后续流程使用。

3.1.3 拦截器实现拦截器集成接口HandlerInterceptor,实现拦截,接口方法有下面三种:

  • preHandler(HttpServletRequest request, HttpServletResponse response, Object handler) 方法将在请求处理之前进行调用。SpringMVC中的Interceptor同Filter一样都是链式调用。每个Interceptor的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor中的preHandle方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean 类型的,当它返回为false时,表示请求结束,后续的Interceptor和Controller都不会再执行;当返回值为true时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。

  • postHandler(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。

  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。总结一点就是:preHandle是请求执行前执行postHandle是请求结束执行afterCompletion是视图渲染完成后执行

3.2 拦截器实现

3.2.1

上面我们已经介绍了过滤器的配置方法,接下来我们再来看看如何配置一个拦截器。我们使用拦截器来实现上面同样的功能,记录请求的执行时间。首先我们实现拦截器类:

public class LogCostInterceptor implements HandlerInterceptor{long start =System.currentTimeMillis();@Overridepublicboolean preHandle(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,Object o) throws Exception{start =System.currentTimeMillis();return true;}@Overridepublic void postHandle(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,Object o,ModelAndView modelAndView) throws Exception{System.out.println("Interceptor cost="+(System.currentTimeMillis()-start));}@Overridepublicvoid afterCompletion(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,Object o,Exception e)throwsException{}
}

3.3.2

这里我们需要实现HandlerInterceptor这个接口,这个接口包括三个方法,preHandle是请求执行前执行的,postHandler是请求结束执行的,但只有preHandle方法返回true的时候才会执行,afterCompletion是视图渲染完成后才执行,同样需要preHandle返回true,该方法通常用于清理资源等工作。除了实现上面的接口外,我们还需对其进行配置:

@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter{@Overridepublic void addInterceptors(InterceptorRegistry registry){registry.addInterceptor(newLogCostInterceptor()).addPathPatterns("/**");super.addInterceptors(registry);}
}

这里我们继承了WebMVCConfigurerAdapter,看过前面的文章的朋友应该已经见过这个类了,在进行静态资源目录配置的时候我们用到过这个类。这里我们重写了addInterceptors这个方法,进行拦截器的配置,主要配置项就两个,一个是指定拦截器,第二个是指定拦截的URL。现在我们再启动系统访问任意一个URL:

https://pic1.zhimg.com/80/v2-1ea7f81701d182f0c02c0b9bcdeb3aec_1440w.jpg

可以看到,我们通过拦截器实现了同样的功能。不过这里还要说明一点的是,其实这个实现是有问题的,因为preHandle和postHandle是两个方法,所以我们这里不得不设置一个共享变量start来存储开始值,但是这样就会存在线程安全问题。当然,我们可以通过其他方法来解决,比如通过ThreadLocal就可以很好的解决这个问题,有兴趣的同学可以自己实现。不过通过这一点我们其实可以看到,虽然拦截器在很多场景下优于过滤器,但是在这种场景下,过滤器比拦截器实现起来更简单。


http://chatgpt.dhexx.cn/article/WFf6TKrW.shtml

相关文章

【java】Filter过滤器

强烈推荐一个大神的人工智能的教程:http://www.captainai.net/zhanghan 一、简介 Filter也称为过滤器,是Servlet中的一项技术,可以管理Web服务器管理的一系列资源,例如jsp,html等。Servlet API中提供了一个Filter接口&#xff0c…

[Java]过滤器(Filter)

一、什么是过滤器 过滤器是Servlet的高级特性之一,是实现Filter接口的Java类! 过滤器的执行流程: 从上面的图我们可以发现,当浏览器发送请求给服务器的时候,先执行过滤器,然后才访问Web的资源。服务器响应…

Java中的过滤器Filter

本文用于学习所用,有不足及错误之处欢迎指出和补充。 目录 一:Filter简介 二:关于Filter (一)如何使用Filter进行过滤 (二)过滤器链 (FilterChain) (三)Filter的配置…

Java之过滤器

一.基本定义: 过滤器实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理 通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理 二.新建一个Filter: 可以直接new一个Filter类.输入过滤器名称,跟创…

java过滤器(Filter)

目录 1 过滤器简介 2 Filter详细介绍 3 Filter的用法 3.1 用法1 3.2 用法2 1 过滤器简介 filter也称之为过滤器,它是javaWeb三大组件之一(Servlet程序、Listener监听器、Filter过滤器) 作用:既可以对请求进行拦截&#xff0…

Java Web之过滤器(Filter)

过滤器(Filter) 过滤器实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理 通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理 大概流程图如下 应用场景 自动登录 统一设置编码格式 访问权限控制 敏感字符…

C#生成二维码和条形码并实现打印的功能

转载:https://www.cnblogs.com/xixim/p/4589078.html 下载地址:http://pan.baidu.com/s/1kTr3Vuf Step1:使用VS2010新建一个窗体程序项目: Step2:添加三个类:分别是BarCodeClass.cs、DocementBase.cs、im…

web项目js调用斑马打印机打印二维码

斑马打印机打印二维码 项目(Web项目)功能中存在生成并打印二维码的功能,需要借助打印机打印出二维码。由于业务需求二维码需要打印在不干胶的材料上并可以进行粘贴,所以借助斑马打印机通过热敏不干胶纸进行打印。 需要结合所使用…

python实现扫描二维码并打印数据

编译环境 1、操作系统:windows 10 2、语言:python 3.7.0 3、编辑器:pycharm-community-2018.2.8 4、需要提前安装的库:pyzbar、opencv-python 代码 # 首先导入本次所需要的库,最后一个csv是Python自带的csv表格操…

uni-app H5+ 连接蓝牙打印机打印文字及二维码

基于Native.js 实现的连接蓝牙打印机 打印效果图核心代码测试代码运行设备及环境PS:PPS:Demo 打印效果图 核心代码 /*** Description: 蓝牙打印类 基于h5 Native.js* Author: EricLee* Date: 2020-10-14 13:53:23* Param: mod* Return: $*/export cons…

5,uniapp功能之—打印机,打印文本和二维码等,(佳博的打印机)

效果图: 思路:1,一个打印按钮,2点击按钮弹窗一个蓝牙模块,选择蓝牙进行连接,连接成功就直接进行打印了,3,打印的内容自己设置 项目结构: 上代码,打印机参数…

批量生成二维码、打印

推荐使用GoodMES云标签打印,地址为:https://t.goodmes.com/home 1、登陆后点击设计与打印——>数据表 2、需要下载云标签打印 3、下载后进行登陆 4、登陆后无需管它,放在那运行即可 5、这个时候你的云标签助手就会现在在线状态 6、点…

electron打印条形码、二维码

功能:在electron打印条形码或者二维码 在百度搜索找不到合适的博客与插件,就在github上找到一个插件 electron-pos-printer 可以一键打印图片、文本、二维码、条形码、表格 不用安装其他多余插件,亲测十分好用 1、安装 npm install ele…

佳博打印机打印条码和二维码的方法

最近项目需求连接蓝牙打印机打印小票 其中小票中有条码和二维码,很多朋友刚接触打印接的打印逻辑,看不太明白,因此我之前给各位提供现成的打印方法: 关键就是安装打印的文档 提前写好各种打印的调用发放,直接在打印模…

【C#】简单二维码制作和打印

系列文章 【C#】条码管理操作手册 本文链接:https://blog.csdn.net/youcheng_ge/article/details/126589496 【C#】IIS平台下,WebAPI发布及异常处理 本文链接:https://blog.csdn.net/youcheng_ge/article/details/126539836 【C#】简单二维…

一维码二维码的生成及打印

VUE条形码及二维码的生成及输出到打印机 文章目录 VUE条形码及二维码的生成及输出到打印机1. 条形码的生成2. 二维码的生成3. 输出打印4. 将代码提取一下 1. 条形码的生成 安装插件 npm install jsbarcode --save github地址: https://github.com/lindell/JsBarcode…

C#二维码的生成及打印

窗体设计显示图 一&#xff0c;生成二维码 /// <summary>/// 生成二维码/// </summary>/// <param name"text">内容</param>/// <param name"width">宽度</param>/// <param name"height">高度</p…

生成二维码,并且打印

生成二维码&#xff0c;并且打印出来 加入依赖 //二维码依赖 npm install --save qrcodejs2 //打印依赖 npm install vue-print-nb --save在mian文件夹中使用引入并使用&#xff0c;或者按需引入 //打印依赖 import Print from vue-print-nb Vue.use(Print)本次二维码是按需引…

二维码打印

1. 二维码简介 二维码&#xff08;2-dimensional bar code&#xff09;&#xff0c;又称二维条码&#xff0c;它是用特定的几何图形按一定规律在平面&#xff08;二维方向&#xff09;上分布的黑白相间的图形&#xff0c;是所有信息数据的一把钥匙。在现代商业活动中&…

vue生成条形码和二维码并打印

文章目录 前言一、生成条形码二、生成二维码三、效果图四、打印 前言 最近有一个需求&#xff0c;需要将产品信息生成标签&#xff0c;每个信息生成一个条形码&#xff0c;拿到所有数据生成二维码&#xff0c;最后打印标签。 一、生成条形码 使用jsbarcode&#xff0c;直接in…