interceptor:一个拦截器
拦截器:是springmvc框架中的一种对象,类似过滤器。 拦截器的主要作用是拦截用户的请求。
可以截断请求,不被处理。 所以可以使用拦截器做登录的验证,权限的检查,日志打印。
拦截器的执行时间:在适配器对象获取之后,在处理器方法执行之前。拦截用户的请求。
拦截器的数量:在一个项目中拦截器可以有0到多个。 拦截器是全局的,对象项目中的所有Controller都可以使用拦截器。
拦截器的创建:
1.新建类,实现框架的中接口HandlerInterceptor, HandlerInterceptor是拦截器接口
2.springmvc配置文件中,声明拦截器的对象, 并指定拦截的请求uri地址
public class MyInterceptor implements HandlerInterceptor {
private long btime;
/**
* preHandle:预处理方法,请求首先到达此方法。可以在方法中对请求做判断,处理。
* 在处理器方法之前执行的。
*
* 参数:
* Object handler : 处理器对象。
* 返回值: boolean
* true:请求是正确的,可以被处理。请求可以通过拦截器
* 拦截器MyInterceptor的【preHandle】
====执行MyController处理器的doSome()====
拦截器MyInterceptor的 【postHandle】
拦截器MyInterceptor的 【afterCompletion】
* false:请求是不正确的,不能被处理。 请求被截断。
* 拦截器MyInterceptor的【preHandle】
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler)throws Exception {
btime = System.currentTimeMillis();
System.out.println("拦截器MyInterceptor的【preHandle】");
//request.getRequestDispatcher("/result.jsp").forward(request, response);
return true;
}
/**
* postHandle:后处理方法。在处理器方法执行之后执行的。 可以获取到处理器方法的返回值
* ModelAndView,
* 可以修改Model中的数据, 修改视图View. 对请求的处理结果做二次修改。
*
参数:
* Object handler : 处理器对象。
* ModelAndView mv: 处理器方法的返回值, 也就是请求的处理结果
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler,ModelAndView mv) throws Exception {
System.out.println("拦截器MyInterceptor的 【postHandle】");
//对请求的处理结果做二次的修正
if( mv != null){
//修改数据
mv.addObject("mydate", new Date());
//修改视图
mv.setViewName("other");
}
}
/**
* afterCompletion:最后执行的方法。在视图View对象处理完成后执行的。
* 此方法执行,意味着请求处理完成。
* 只要当前拦截器的preHandle返回true,afterCompletion方法一定执行。
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("拦截器MyInterceptor的 【afterCompletion】");
//最后执行的,一般做资源回收, 内存的释放。
long etime = System.currentTimeMillis();
System.out.println("请求的处理时长:"+(etime -btime));
}
}
多个拦截器情况下执行顺序
执行结果
执行流程解析:
源代码:
查看中央调度器 DispatcherServlet 的 doDispatch()方法源码:在执行处理器方法之前,
会执行处理器执行链对象 mappedHandler 的 applyPreHandle()方法。然后执行 Handler,最后
执行处理器执行链对象的 applyPostHandle()方法。
applyPreHandle()方法用于执行处理器执行链中的所有拦截器的 preHandle() 方法。
applyPreHandle()方法的返回结果取决于执行链中的每一个拦截器的 preHandle()方法。只要
有一个 preHandle()方法返回 false,则其就会返回 false。然后就执行了 return;即结束了
doDispatch()方法,即该请求的处理结束。
对 于 处 理 器 执 行 链 的 applyPostHandle() 方 法 ,
其 是 循 环 倒 序 执 行 所 有 拦 截 器 的postHandle()方法的。
那么 afterCompletion()方法是什么时候执行的呢?
在 刚 才 的 处 理 器 执 行 链 的 applyPreHandle() 方 法 中 看 到 , 若 存 在 任 一个拦截器的
preHandle()方法返回 false,则会调用执行处理器执行链的 triggerAfterCompletion()方法,即
会触发所有 afterCompletion()方法的执行。
在 doDispatch()方法中也存在一个 catch(){}语句,表示若发生异常,则会调用执行
triggerAfterCompletion()方法。
但在正常情况下,即所有的 preHandle()方法返回均为 true,且 doDispatch()方法没有异
常发生的情况下,afterCompletion()方法是在视图解析器后执行的。
查看中央调度器 DispatcherServlet 的 processDispatchResult()方法源码可知,在对视图渲
染 过 后 , 会 调 用 执 行 处 理 器 执 行 链 的 triggerAfterCompletion() 方 法 , 即 执 行 所 有 的
afterCompletion()方法。
打 开 处 理 器 执 行 链 的 triggerAfterCompletion() 方 法 , 可 以 看 到 , 其 对 拦 截 器 的
afterCompletion()方法的执行,也是循环倒序执行的。
哥哥们 我尽力了