详解拦截器和过滤器

目录

  • 代码演示
    • 过滤器Demo
    • 拦截器Demo
  • 过滤器
    • 自定义拦截器
    • 配置拦截器
    • 过滤器执行原理
    • 多个过滤器的执行顺序
  • 拦截器
    • 自定义拦截器
    • 注册拦截器
      • 1)注册拦截器
      • 2)配置拦截的路径
      • 3)配置不拦截的路径
    • 多个拦截器的执行顺序
  • 过滤器和拦截器的区别

代码演示

我们这里先上代码,看看拦截器和过滤器在代码实现上的区别。

过滤器Demo

1、定义一个类,实现接口Filter

public class FilterDemo implements Filter {
}

2、实现Filter接口的方法

public class FilterDemo implements Filter {public static int i = 0;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("执行init方法");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("执行doFilter方法 + " + i++);filterChain.doFilter(servletRequest,servletResponse);}@Overridepublic void destroy() {System.out.println("执行destroy方法");}
}

3、配置拦截路径

1)通过web.xml文件配置

<filter><filter-name>FilterDemo</filter-name><filter-class>com.example.springboot_demo.filter.FilterDemo</filter-class>
</filter><filter-mapping><filter-name>FilterDemo</filter-name><!-- 拦截路径 --><url-pattern>/*</url-pattern>
</filter-mapping>

2)、注解
@WebFilter("/*")

拦截器Demo

1、定义一个类实现HandlerInterceptor 并实现此接口的方法

public class InterceptorDemo implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("执行preHandle方法");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("执行postHandle方法");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("执行afterCompletion方法");}
}

2、创建一个配置类,实现WebMvcConfigurer

@Configuration
public class MyConfig implements WebMvcConfigurer {}

3、实现WebMvcConfigurer addInterceptors方法

@Configuration
public class MyConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {}
}

4、将自定义的拦截器进行注册,并配置拦截路径和放行路径

@Configuration
public class MyConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册自定义的拦截器InterceptorRegistration interceptorRegistration = registry.addInterceptor(new InterceptorDemo());// 定义拦截所有路径interceptorRegistration.addPathPatterns("/**");// 定义排查/user/下的所有路径interceptorRegistration.excludePathPatterns("/user/**");}
}

这就是过滤器和拦截器的代码实现,展示了它们在代码层面的不同。后面将会进行详细解释。

过滤器

过滤器是Servlet的高级特性之一,就是Web服务器在处理请求的时候会经过每一过滤器再处理请求。
在这里插入图片描述

自定义拦截器

自定义拦截器其实就是实现Filter接口,然后实现他的方法。

那它的方法都有什么作用呢?
1)init方法
public void init(FilterConfig filterConfig)

  • 在Web容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。
  • 注意:这个方法必须执行成功,否则过滤器会不起作用。

2)doFilter方法
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)

  • 容器中的每一次请求都会调用该方法
  • 一次请求会调用两次,进Web容器时调用一次,出Web容器时调用一次
  • 要使用filterChain.doFilter(servletRequest, servletResponse);来调用下一个过滤器,否则这个请求就到此结束了。

3)destroy方法
public void destroy()

  • 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源
  • 在过滤器 Filter 的整个生命周期也只会被调用一次
public class FilterDemo implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("执行init方法");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("执行doFilter方法");filterChain.doFilter(servletRequest,servletResponse);}@Overridepublic void destroy() {System.out.println("执行destroy方法");}
}

配置拦截器

1)通过web.xml文件配置

<filter><filter-name>FilterDemo</filter-name><filter-class>com.example.springboot_demo.filter.FilterDemo</filter-class>
</filter>
  • <filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
  • <filter-class>元素用于指定过滤器的完整的限定类名。
  • <init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。
<filter-mapping><filter-name>FilterDemo</filter-name><!-- 拦截路径 --><url-pattern>/*</url-pattern>
</filter-mapping>
  • <filter-mapping>元素用于设置一个Filter 所负责拦截的资源。
  • <filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字。
  • <url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)

2)、注解
@WebFilter(filterName = "FilterDemo",urlPatterns = "/*")

  • 理解了web.xml方式,注解方式看起来就一目了然了

过滤器执行原理

过滤器执行主要是通过函数回调的方式。
在我们自定义的过滤器中都会实现一个 doFilter()方法,这个方法有一个FilterChain 参数,而实际上它是一个回调接口。
在这里插入图片描述
所以,如果我们写这样的过滤器

public class FilterDemo implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("执行init方法");}@Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {System.out.println("准备放行");//执行这一句,说明放行(让下一个过滤器执行,或者执行目标资源)chain.doFilter(req, resp);System.out.println("放行完成");}@Overridepublic void destroy() {System.out.println("执行destroy方法");}
}

程序在执行到chain.doFilter(req,resp)时会执行下一个过滤器或目标资源,然后执行完成回到此方法继续往下执行。

多个过滤器的执行顺序

过滤器之间的执行顺序看在web.xml文件中mapping的先后顺序的,如果放在前面就先执行,放在后面就后执行!
如果是通过注解的方式配置,就比较urlPatterns的字符串优先级

拦截器

拦截器是SpringMVC自己的功能,虽然看起来和过滤器一样,但是底层使用的是面向切面编程AOP

自定义拦截器

前面我们直到自定义拦截器要实现HandlerInterceptor接口,然后再实现它的方法。

那这几个方法都有什么作用呢?
1)preHandle方法
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler);

  • 再请求处理之前执行(Controller方法调用之前)
  • 返回值是boolean类型,返回false表示拦截,不会让此请求访问Controller,返回true则可继续执行

2)postHandle方法
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView);

  • 在请求结束之后(Controller请求返回),在ModelAndView渲染之前调用
  • 主要就是用来对ModelAndView对象进行操作

3)afterCompletion方法
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);

  • 在整个请求结束之后调用
  • 主要是用于资源清理工作
public class InterceptorDemo implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("执行preHandle方法");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("执行postHandle方法");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("执行afterCompletion方法");}
}

注册拦截器

创建一个实现WebMvcConfigurer的拦截器,然后将自定义的拦截器注册到其中。可以注册多个拦截器。

实现方法addInterceptors,通过参数InterceptorRegistry registry来进行一系列配置

@Configuration
public class MyConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册自定义的拦截器InterceptorRegistration interceptorRegistration = registry.addInterceptor(new InterceptorDemo());// 定义拦截所有路径interceptorRegistration.addPathPatterns("/**");// 定义排查/user/下的所有路径interceptorRegistration.excludePathPatterns("/user/**");// 确定执行顺序interceptorRegistration.order(1);}
}

1)注册拦截器

InterceptorRegistration interceptorRegistration = registry.addInterceptor(new InterceptorDemo());
将自定义的拦截器对象传入其中即可,如果要注册多个拦截器,调用多次这个方法即可。

2)配置拦截的路径

interceptorRegistration.addPathPatterns("/**");

如果需要拦截多个路径,可以多次传入一个字符串,也可以传入一个List集合。
在这里插入图片描述

3)配置不拦截的路径

interceptorRegistration.excludePathPatterns("/user/**");

这个和addPathPatterns一样,可以传入字符串,也可以传入List
在这里插入图片描述

多个拦截器的执行顺序

在这里插入图片描述

多个拦截器可通过order()方法来确定执行顺序,order()传入一个数字,数字越小则越先执行。

过滤器和拦截器的区别

  • 适用范围不同:Filter是Servlet容器规定的,只能使用在servlet容器中,而拦截器的使用范围就大得多
  • 使用的资源不同:拦截器是属于spring的一个组件,因此可以使用spring的所有对象,如service对象,数据源,事务控制等,而过滤器就不行
  • 深度不同:Filter还在servlet前后起作用。而拦截器能够深入到方法前后,异常抛出前后,因此拦截器具有更大的弹性,所有在spring框架中应该优先使用拦截器
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/95160.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用Spark/Flink等分布式计算引擎做网络入侵检测

如何使用Spark/Flink等分布式计算引擎做网络入侵检测 引言16 Distributed Abnormal Behavior Detection Approach Based on Deep Belief Network and Ensemble SVM Using Spark17 Spark configurations to optimize decision tree classification on UNSW-NB1518 A dynamic spa…

elementUI 的上传组件<el-upload>,自定义上传按钮样式

方法一&#xff1a; 原理&#xff1a;调用<el-upload>组件的方法唤起选择文件事件 效果&#xff1a; 页面代码&#xff1a; 1、选择图片按钮 <div class"flex_row_spacebetween btn" click"chooseImg"><span class"el-icon-plus ic…

【QT】 QFileQFileInfo文件操作

很高兴在雪易的CSDN遇见你 &#xff0c;给你糖糖 欢迎大家加入雪易社区-CSDN社区云 前言 本文分享QT对文件的操作技术&#xff0c;希望对各位小伙伴有所帮助&#xff01; 感谢各位小伙伴的点赞关注&#xff0c;小易会继续努力分享&#xff0c;一起进步&#xff01; 你的点…

Vue3 —— watchEffect 高级侦听器

该文章是在学习 小满vue3 课程的随堂记录示例均采用 <script setup>&#xff0c;且包含 typescript 的基础用法 前言 Vue3 中新增了一种特殊的监听器 watchEffect&#xff0c;它的类型是&#xff1a; function watchEffect(effect: (onCleanup: OnCleanup) > void,o…

go_并发编程(1)

go并发编程 一、 并发介绍1&#xff0c;进程和线程2&#xff0c;并发和并行3&#xff0c;协程和线程4&#xff0c;goroutine 二、 Goroutine1&#xff0c;使用goroutine1&#xff09;启动单个goroutine2&#xff09;启动多个goroutine 2&#xff0c;goroutine与线程3&#xff0…

通过 HttpClient 发送请求

文章目录 1. 引入 maven 依赖2. 发送 GET 方式的请求3. 发送 POST 方式的请求 1. 引入 maven 依赖 <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId> </dependency>2. 发送 GET 方式的请求…

C++类型转换

目录 隐式类型转换 转型方向 整型提升和截断 显示转换的种类 C风格的强制类型转换 C风格的函数样式转换 隐式类型转换 转型方向 隐式类型转换&#xff0c;又称自动转换、算数转换&#xff0c;是由编译器自动完成的类型转换称为隐式类型转换。自动转换的原则为&#xff…

Leaflet入门,Leaflet如何实现vue双向绑定数据添加到图片标记物到地图上,动态根据vue数据更新到地图上以及鼠标经过标记物显示提示框

前言 本章使用Leaflet的vue2-leaflet或者vue-leaflet插件方式实现vue数据绑定地图数据,实现地图标记物与vue数据的双向联动更新,以及鼠标经过标记物显示提示框功能。 实现效果演示 vue如何使用Leaflet vue2如何使用:《Leaflet入门,如何使用vue2-leaflet实现vue2双向绑定…

GaussDB数据库SQL系列-子查询

目录 一、前言 二、GaussDB SQL子查询表达式 1、EXISTS/NOT EXISTS 2、IN/NOT IN 3、ANY/SOME 4、ALL 三、GaussDB SQL子查询实验示例 1、创建实验表 2、EXISTS/NOT EXISTS示例 3、IN/NOT IN 示例 4、ANY/SOME 示例 5、ALL示例 四、注意事项及建议 五、小结 一、…

msvcp110.dll是什么意思,msvcp110.dll丢失的解决方法

装好软件或游戏之后&#xff0c;一打开就跳出各种报错信息的情况小伙伴一定见过&#xff0c;其中缺少各种msvcp110.dll文件最常见。小伙伴们一定奇怪&#xff0c;用得好好的电脑&#xff0c;怎么会缺文件呢&#xff1f;为啥其他游戏/应用就没事呢&#xff1f;其实这些“丢失”的…

LVS负载均衡群集部署(LVS-NAT模型实例)

一、集群 1.1集群的含义 Cluster&#xff0c;集群、群集,为解决某个特定问题将多台计算机组合起来形成的单个系统。 由多台主机构成&#xff0c;但对外只表现为一个整体。 1.2群集的三种类型 1.2.1负载均衡群集 LB&#xff1a; Load Balancing&#xff0c;负载均衡&#x…

国产化系统中遇到的视频花屏、卡顿以及延迟问题的记录与总结

目录 1、国产化系统概述 1.1、国产化操作系统与国产化CPU 1.2、国产化服务器操作系统 1.3、当前国产化系统的主流配置 2、视频解码花屏与卡顿问题 2.1、视频解码花屏 2.2、视频解码卡顿 2.3、关于I帧和P帧的说明 3、国产显卡处理速度慢导致图像卡顿问题 3.1、视频延…

【C++类和对象】类有哪些默认成员函数呢?(下)

文章目录 一、类的6个默认成员函数二、日期类的实现2.1 运算符重载部分2.2 日期之间的运算2.3 整体代码1.Date.h部分2. Date.cpp部分 三. const成员函数四. 取地址及const取地址操作符重载扩展内容 总结 ヾ(๑╹◡╹)&#xff89;" 人总要为过去的懒惰而付出代价ヾ(๑╹◡…

【Rust】Rust学习 第十二章一个 I/O 项目:构建一个命令行程序

本章既是一个目前所学的很多技能的概括&#xff0c;也是一个更多标准库功能的探索。我们将构建一个与文件和命令行输入/输出交互的命令行工具来练习现在一些你已经掌握的 Rust 技能。 Rust 的运行速度、安全性、单二进制文件输出和跨平台支持使其成为创建命令行程序的绝佳选择…

2023上半年京东手机行业品牌销售排行榜(京东数据平台)

后疫情时代&#xff0c;不少行业都迎来消费复苏&#xff0c;我国智能手机市场在今年上半年也实现温和的复苏&#xff0c;手机市场的出货量回暖。 根据鲸参谋平台的数据显示&#xff0c;2023年上半年&#xff0c;京东平台上手机的销量为2830万&#xff0c;环比增长约4%&#xf…

sql中union all、union、intersect、minus的区别图解,测试

相关文章 sql 的 join、left join、full join的区别图解总结&#xff0c;测试&#xff0c;注意事项 1.结论示意图 对于intersect、minus&#xff0c;oracle支持&#xff0c;mysql不支持&#xff0c;可以变通&#xff08;in或exists&#xff09;实现 2.创建表和数据 -- 建表…

Android Socket使用TCP协议实现手机投屏

本节主要通过实战来了解Socket在TCP/IP协议中充当的是一个什么角色&#xff0c;有什么作用。通过Socket使用TCP协议实现局域网内手机A充当服务端&#xff0c;手机B充当客户端&#xff0c;手机B连接手机A&#xff0c;手机A获取屏幕数据转化为Bitmap&#xff0c;通过Socket传递个…

Linux——KVM虚拟化

目录标题 虚拟化技术虚拟化技术发展案例KVM简介KVM架构及原理KVM原理KVM虚拟化架构/三种模式虚拟化前、虚拟化后对比KVM盖中盖套娃实验 虚拟化技术 通过虚拟化技术将一台计算机虚拟为多台逻辑计算机&#xff0c;在一台计算机上同时运行多个逻辑计算机&#xff0c;同时每个逻辑…

ValueError: check_hostname requires server_hostname

ValueError: check_hostname requires server_hostname 可能是代理的问题&#xff0c;在pip下载库的时候如果之前电脑连过梯子&#xff0c;就会出现。 这个时候就算关掉梯子也无法解决这个错误。 下面是解决方法 右键网络&#xff0c;打开设置&#xff0c;代理 点击手动设置代…

excel 之 VBA

1、excel和VBA 高效办公&#xff0c;把重复性的工作写成VBA代码&#xff08;VB代码的衍生物&#xff0c;语法和VBA相同&#xff09;。 首先打开开发工具模式&#xff0c;如果没有选显卡&#xff0c;需要手动打开 打开程序编辑界面 快捷键 altF11一般操作 程序调试&#xf…