大家好,我是IT修真院武汉分院第15期的学员,一枚正直纯洁善良的java程序员
今天给大家分享一下,修真院官网Java任务五,深度思考中的知识点——拦截器,过滤器,监听器
1.背景介绍
拦截器
Interceptor是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个Action执行的前后执行的代码,也可以在一个Action执行前阻止其执行 。同时也提供了一种可以提取Action中可重用的部分的方式。
过滤器
Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码,做一些业务逻辑判断,过滤器随web应用启动而启动,只初始化一次,只有当web应用停止或重新部署才销毁
监听器
Listener是实现了javax.servlet.ServletContextListener接口的服务器端程序,它也是随web应用的启动而启动,只初始化了一次,随web应用的停止而销毁.
2.知识剖析
拦截器的实现方法: 主要通过两种途径,第一种是实现HandlerInterceptor接口,第二种是实现WebRequestInterceptor接口。
(1)HandlerInterceptor 接口
在该接口中,定义了 3 个方法,分别为preHandle()、postHandle()和afterCompletion(),通过复写这 3 个方法来对用户的请求进行拦截处理。
而且在 Spring 框架中,还提供了另外一个接口和一个抽象类,实现了对HandlerInterceptor接口的功能扩展,分别为:AsyncHandlerInterceptor和HandlerInterceptorAdapter.
在实际应用中,一般都是通过实现HandlerInterceptor接口或者继承HandlerInterceptorAdapter抽象类
1)preHandle方法,该方法在请求处理之前进行调用。
SpringMVC 中的 Interceptor 是链式调用的,在一个请求中可以同时存在多个 Interceptor 。每个 Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是preHandle 方法,因此可以在这个方法中进行一些前置初始化操作或者是对当前请求做一个预处理,也可以进行一些判断来决定请求是否要继续进行下去。
当它返回为 false 时,表示请求结束,后续的 Interceptor 和 Controller 都不会再执行;
当返回值为 true 时,就会继续调用下一个 Interceptor 的 preHandle 方法,如果已经是最后一个 Interceptor 的时候,就会调用当前请求的 Controller 中的方法。
2)postHandle方法在在当前所属的 Interceptor 的 preHandle 方法的返回值为 true 的时候,才能被调用。
当前请求被处理之后,也就是在 Controller 中的方法调用之后执行,但是它会在 DispatcherServlet 进行视图返回渲染之前被调用,所以可以在这个方法中对 Controller 处理之后的 ModelAndView 对象进行操作。
postHandle 方法被调用的方向跟 preHandle 是相反的,先声明的 postHandle 方法反而会后执行。
3)afterCompletion方法,也是需要当前对应的 Interceptor 的 preHandle 方法的返回值为 true 时才会执行。因此,该方法将在整个请求结束之后,也就是在 DispatcherServlet 渲染了对应的视图之后执行,这个方法的主要作用是用于进行资源清理的工作。
(2)WebRequestInterceptor 接口
在此接口中也定义了 3 个方法,同HandlerInterceptor接口完全相同,也需要复写这 3 个方法来对用户的请求进行拦截处理。而且这 3 个方法都传递了同一个参数 WebRequest。
它里面的方法定义跟 HttpServletRequest 类似,在WebRequestInterceptor中对 WebRequest 进行的所有操作都将同步到 HttpServletRequest 中,然后在当前请求中依次传递。
1)preHandle(WebRequest request)方法,该方法跟 HandlerInterceptor 中的 preHandle 不同,主要区别在于该方法无返回值。因此不能通过返回值决定是否终止请求。其主要作用是进行资源的准备工作。
2)postHandle(WebRequest request, ModelMap model)方法,同样也是在controller之后,视图返回被渲染之前被调用。该方法有两个参数,WebRequest 对象是用于传递整个请求数据的,比如在 preHandle 中准备的数据都可以通过 WebRequest 来传递和访问;
3)afterCompletion(WebRequest request, Exception ex)方法,同样是在视图渲染之后调用,主要用来进行资源的释放。
过滤器
Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter 技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。
Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:
调用目标资源之前,让一段代码执行;
是否调用目标资源(即是否让用户访问web资源);
调用目标资源之后,让一段代码执行。
web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对 象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方 法,即web资源就会被访问,否则web资源不会被访问。
过滤器中的方法
init: 程序启动时,web服务器将创建Filter的实例对象,并调用其init方法,完成对象的初始化 功能;filter对象只会创建一次,init方法也只会执行一次。
doFilter:当访问web服务器时对请求进行操作。
destroy:web容器调用destroy方法销毁Filter。destroy方法在Filter的生命周期中仅执行一次。在destroy方法中,可以释放过滤器使用的资源。
监听器
监听web应用,监听许多信息的初始化,销毁,增加,修改,删除等 。
监听器对象可以在事情发生前、发生后可以做一些必要的处理。
监听器的分类
1、ServletContext监听
ServletContextListener:用于对Servlet整个上下文进行监听(创建、销毁)。
ServletContextAttributeListener:对Servlet上下文属性的监听(增删改属性)。
2、Session监听
HttpSessionListener接口:对Session的整体状态的监听。
HttpSessionAttributeListener接口:对session的属性监听。
3、Request监听
ServletRequestListener:用于对Request请求进行监听(创建、销毁)。
ServletRequestAttributeListener:对Request属性的监听(增删改属性)。
3.常见问题
配置文件中的多个同样类型的处理器的执行顺序是怎样的?
4.解决方案
在web.xml中如果配置了多个过滤器,那么会根据配置文件的中我们自己声明的顺序来执行;同理多个拦截器的执行顺序也是这样的。
5.编码实战
6.扩展思考
各自应用场景:
两者的本质区别:从灵活性上说拦截器功能更强大些,Filter能做的事情,Interceptor都能做,而且可以在请求前,请求后执行,比较灵活。Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录状态之类),太细的话,还是建议用interceptor。Filter只在Servlet前后起作用。而拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。所以在Spring构架的程序中,优先使用拦截器。
7.参考文献
链接:https://baike.baidu.com/item/MyBatis/2824918?fr=aladdin
作者:百度百科
链接:https://www.w3cschool.cn/
作者:w3cschool
链接:https://blog.csdn.net/wangyongxia921/article/details/46272813
作者:_Cassie
http://how2j.cn/k/spring/spring-aop/89.html#step5306
作者:how2j
链接:https://www.cnblogs.com/fenglie/articles/4097759.html
作者:fenglie
8.更多讨论
问题一:过滤器和拦截器的区别?
①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
问题二:过滤器和拦截器的执行顺序?
过滤器和拦截器的执行顺序:过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。拦截器是被包裹在过滤器之中的。
问题三:各自应用场景?
两者的本质区别:从灵活性上说拦截器功能更强大些,Filter能做的事情,Interceptor都能做,而且可以在请求前,请求后执行,比较灵活。Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录状态之类),太细的话,还是建议用interceptor。Filter只在Servlet前后起作用。而拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。所以在Spring构架的程序中,优先使用拦截器。
今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~