spingmvc interceptor

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()方法的执行,也是循环倒序执行的。

在这里插入图片描述

哥哥们 我尽力了
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/rdz_NNN/article/details/88428304