处理器拦截器(HandlerInterceptor)详解

news/2024/7/3 1:34:25

处理器拦截器(HandlerInterceptor)详解

96 
编程界的小学生 
2017.04.06 15:19* 字数 881 阅读 657评论 0

简介
SpringWebMVC的处理器拦截器,类似于Servlet开发中的过滤器Filter,用于处理器进行预处理和后处理。

应用场景
1、日志记录,可以记录请求信息的日志,以便进行信息监控、信息统计等。
2、权限检查:如登陆检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。
3、性能监控:典型的是慢日志。

HandlerInterceptor

public interface HandlerInterceptor {/*** 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller* 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;*/boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception;/*** 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。*/void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;/*** 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中*/void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;}

拦截器适配器HandlerInterceptorAdapter
有时候我们可能只需要实现三个回调方法中的某一个,如果实现HandlerInterceptor接口的话,三个方法必须实现,不管你需不需要,此时spring提供了一个HandlerInterceptorAdapter适配器(种适配器设计模式的实现),允许我们只实现需要的回调方法。

public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {/*** 默认是true*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {return true;}/*** This implementation is empty.*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception {}/*** This implementation is empty.*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {}/*** 不是HandlerInterceptor的接口实现,是AsyncHandlerInterceptor的,AsyncHandlerInterceptor实现了HandlerInterceptor*/@Overridepublic void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {}}

这样在我们业务中比如要记录系统日志,日志肯定是在afterCompletion之后记录的,否则中途失败了,也记录了,那就扯淡了。一定是程序正常跑完后,我们记录下那些对数据库做个增删改的操作日志进数据库。所以我们只需要继承HandlerInterceptorAdapter,并重写afterCompletion一个方法即可,因为preHandle默认是true。

运行流程图

Paste_Image.png

运行流程总结如下:

1、拦截器执行顺序是按照Spring配置文件中定义的顺序而定的。

2、会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则按顺序加载完preHandle方法。

3、然后执行主方法(自己的controller接口),若中间抛出异常,则跟return false效果一致,不会继续执行postHandle,只会倒序执行afterCompletion方法。

4、在主方法执行完业务逻辑(页面还未渲染数据)时,按倒序执行postHandle方法。若第三个拦截器的preHandle方法return false,则会执行第二个和第一个的postHandle方法和afterCompletion(postHandle都执行完才会执行这个,也就是页面渲染完数据后,执行after进行清理工作)方法。(postHandle和afterCompletion都是倒序执行)

正常流程Demo

package com.bshf.recipe.demo.syslog;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class SyslogInterceptor implements HandlerInterceptor {/*** 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller* 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {System.out.println("==========================================1================================================");return true;}/*** 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {System.out.println("==========================================post1================================================");}/*** 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {System.out.println("==========================================after1================================================");}}
package com.bshf.recipe.demo.syslog;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class SyslogInterceptor2 implements HandlerInterceptor {/*** 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller* 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {System.out.println("==========================================2================================================");return true;}/*** 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {System.out.println("==========================================post2================================================");}/*** 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {System.out.println("==========================================after2================================================");}
}
package com.bshf.recipe.demo.syslog;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class SyslogInterceptor3 implements HandlerInterceptor {/*** 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller* 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {System.out.println("==========================================3================================================");return true;}/*** 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {System.out.println("==========================================post3================================================");}/*** 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {System.out.println("==========================================after3================================================");}
}
<mvc:interceptors><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.bshf.recipe.demo.syslog.SyslogInterceptor" /></mvc:interceptor><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.bshf.recipe.demo.syslog.SyslogInterceptor2" /></mvc:interceptor><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.bshf.recipe.demo.syslog.SyslogInterceptor3" /></mvc:interceptor>
</mvc:interceptors>

<mvc:mapping path="/**"/>需要拦截的路径,这里匹配所有。这里的配置顺序将是拦截器执行顺序。

输出结果:

==========================================1================================================
==========================================2================================================
==========================================3================================================
==========================================post3================================================
==========================================post2================================================
==========================================post1================================================
==========================================after3================================================
==========================================after2================================================
==========================================after1================================================

post和after是倒序的!!!!

中断流程Demo
将SyslogInterceptor3的preHandle方法返回false。其他不变,再看输出结果

==========================================1================================================
==========================================2================================================
==========================================3================================================
==========================================after2================================================
==========================================after1================================================

发现没有了post,post方法一个都没有输出。不仅如此,你的主程序代码(xxx.controller的一个接口)都不会被执行,所以只要遇到return false,则直接进行after清理工作,post和自己主程序代码都将被略过。

 

来源:http://www.jianshu.com/p/1e8d088c2be9

http://lihuaxi.xjx100.cn/news/238072.html

相关文章

saltstack实现haproxy+keepalived负载均衡+高可用(二)

一键部署haproxykeepalived实现负载均衡高可用 实验环境&#xff1a; &#xff01;&#xff01;&#xff01;&#xff01; 特别注意&#xff1a; www.westos.org为test1的minion名字 test1: 172.25.1.11 nginx master minion test2: 172.25.…

python学习day3

1丶 用户先进行登陆如果用户名在文件中且用户密码也正确就登陆成功调用购物车函数&#xff0c;如果用户用户名输入正确密码错误&#xff0c;提示用户密码错误且重新输入&#xff0c;如果用户 输入用户名不存在&#xff0c;提示用户是否创建该用户&#xff0c;调用注册函数。 1.…

以太坊交易事件,日志的理解

想知道更多关于区块链技术知识&#xff0c;请百度【链客区块链技术问答社区】 链客&#xff0c;有问必答&#xff01;Ethereum transation event and log 以太坊交易事件的功能有三个&#xff1a; 用于返回智能合约执行过程中的返回值到用户界面同步触发前端用户界面事件便宜的…

Phpcms V9手机门户设置教程:怎么用PC V9做手机网站

一、在PHPcms V9管理后台设置手机门户 1.1、开启手机网站。位置&#xff1a;模块 》手机门户 》 添加手机站点&#xff0c;具体设置可参照截图&#xff1a; 填写站点名和LOGO文件相对位置&#xff0c;绑定用于手机网站的二级域名m.cmsyou.com&#xff0c;域名以http://开头。 1…

中年妇女xxx_2019年国际妇女节庆祝活动

中年妇女xxxBehind the scenes幕后花絮 Becoming Women Techmakers Ambassador成为女性技术制造者大使 In 2018 I decided to start my remote freelance career and to continue to expand my Full Stack Developer knowledge by finishing the last FreeCodeamp projects f…

WPF查找子控件和父控件方法

原文:WPF查找子控件和父控件方法public List<T> GetChildObjects<T>(DependencyObject obj, string name) where T : FrameworkElement{DependencyObject child null;List<T> childList new List<T>();for (int i 0; i < VisualTreeHelper.GetCh…

zabbix简介及基本安装(一)

zabbix简单介绍&#xff1a; 官网&#xff1a;可以进官网查看一下&#xff1a;https://www.zabbix.com/cn/ //英语能力有限的读者可以将由上角的语言调成汉语方便查看 功能&#xff1a;网络监控、服务器监控、云监控、服务监控等。 介绍&#xff1a;zabbix&#xff08;[…

聚类基本概念及常见聚类算法和EM算法

1. 基本概念 1.1 定义 聚类&#xff1a;发现数据中分组聚集的结构&#xff0c;根据数据中样本与样本之间的距离或相似度&#xff0c;依据类内样本距离小&#xff08;相似度大&#xff09;、类间样本距离大&#xff08;相似度小&#xff09;将样本划分为若干组/类/簇。 基于划分…