SpringMVC拦截器执行过程源码分析
2017-04-26 11:45
459 查看
查看博客:拦截器的基本使用
在doDispatch()中,该方法
进入getHandler(processedRequest)方法。
看看HandlerExecutionChain里面到底装了什么。
嗯,没错,里面装了Handler和拦截器,其中每次添加拦截器时,用的是interceptorList这个List对象。
当要获取HandlerExecutionChain里面的拦截器来使用时,就会用到interceptor数组。
我们已经知道,SpringMVC遍历HandlerMapping对象是为了获取到一个HandlerExecutionChain。而我们配置的对象是一个Handler而不是HandlerExecutionChain(Handler和HandlerExecutionChain是两个不同继承树里面的类),所以SpringMVC一定会创建一个HandlerExecutionChain对象,并且返回。
嗯,没错,就是这样。已经返回HandlerExecutionChain了。
在HandlerExecutionChain里面仅有两个构造方法:
两个构造方法非常有趣。
这两个构造方法合起来的意思是:
当我们创建HandlerExecutionChain时,传入的不是一个HandlerExecutionChain对象时,我们默认是不会加入拦截器的,但是我们会加入处理器映射器里面配置的拦截器。
如果我们传入的是一个HandlerExecutionChain对象时,就会加入该对象已有的拦截器,并且也会加入处理器映射器里面的拦截器。
所以啊!我们配置Handler的时候,该Handler也可以是一个HandlerExecutionChain对象。我们可以向HandlerExecutionChain里面注入Handler和拦截器集合,注入时必须注入到interceptors数组变量里面,而不是interceptorList里面,因为interceptorList会被重新在构造方法里面赋值。
创建拦截器:
在SpringMVC核心配置文件中进行配置:
注意:handler必须要注入到HandlerExecutionChain对象里面,否则。。。会抛出异常!!
嗯,感觉挺好的!!但是。。。。
哦豁!!报异常了。。。
那么这种方式是不对的。不能通过无参构造创建HandlerExecutionChai对象,之后再注入参数。
那么我们是否可以继承HandlerExecutionChain,把set方法和无参构造方法添加上呢??
也就是说,我们SpringMVC核心配置文件有变!!
再来尝试访问下:
注意点:
当Handler(处理器)被HandlerExecutionChain替代时。拦截器组的组成由两个部分的拦截器组成。
总的拦截器=HandlerExecutionChain中的拦截器组+处理器映射器里面配置的拦截器。
前提条件:该HandlerExecutionChain对象被配置在该处理器映射器中。
HandlerExecutionChain中拦截器组的存储顺序为,先存储HandlerExecutionChain中的拦截器组,然后才是存储处理器映射器里面配置的拦截器。
嗯,非常Nice!!
继续之前之前之前的分析,目前我们讲到了这里:
当SpringMVC返回一个HandlerExecutionChain对象后。
进入applyPreHandle()方法:
在所有拦截器的applyPreHandle()方法执行完毕后,执行Handler,并且返回一个视图。
拦截器的preHandle()方法一般用来判断请求状态是否满足需要,编码是否需要调整等。
Handler执行完毕后执行postHandle()方法。该方法一般用作处理编码或者判断ModelAndView的结果是否正确,是否还需要调整。
执行所有拦截器的postHandle()方法后执行processDispatchResult()方法。
其中ModelAndView渲染的意思是,解析View,取出Model数据填充到request中,最后进行页面跳转(转发或者包含)。也就是说render()方法执行完毕后,我们客户端(浏览器)就能看到效果了。
render()方法由视图解析器实现。解析器在SpringMVC配置文件中进行配置。
最后的最后执行所有拦截器afterCompletion()方法。该步骤一般是用来释放资源用的。
至此拦截器的执行过程就讲解完毕了。
非常Nice!!!
介绍
从这篇博客我们可以知道,前端SpringMVC前端控制器的主要逻辑基本上都在doDispatch()方法里面。分析
注意: 下面我要说的Handler是一个统称,一个处理器的统称,不是一个类。 实现Handler通常有下面几种方式: 1.实现Controller接口。重写handleRequest()方法 2.继承AbstractController抽象类。特殊功能:该抽象类能够限制哪儿些请求方式(POST,GET)能够访问该Handler。 2.实现HttpRequestHandler接口。重写handleRequest()方法 3.继承MultiActionController。可以在一个类里面写多个方法。 - 方法要求,必须有两个参数。第一个为:HttpServletRequest,第二个为:HttpServletResponse,注意:有顺序要求!!! - 方法名不能为handleRequest。 - 对返回值没有要求。你可以返回ModelAndView类型,也可以是void。
在doDispatch()中,该方法
mappedHandler=getHandler(processedRequest)不仅仅是返回一个Handler对象,其实它是返回一个包含目标Handler和拦截器集合的一个包装类型对象。
进入getHandler(processedRequest)方法。
看看HandlerExecutionChain里面到底装了什么。
嗯,没错,里面装了Handler和拦截器,其中每次添加拦截器时,用的是interceptorList这个List对象。
当要获取HandlerExecutionChain里面的拦截器来使用时,就会用到interceptor数组。
我们已经知道,SpringMVC遍历HandlerMapping对象是为了获取到一个HandlerExecutionChain。而我们配置的对象是一个Handler而不是HandlerExecutionChain(Handler和HandlerExecutionChain是两个不同继承树里面的类),所以SpringMVC一定会创建一个HandlerExecutionChain对象,并且返回。
嗯,没错,就是这样。已经返回HandlerExecutionChain了。
在HandlerExecutionChain里面仅有两个构造方法:
两个构造方法非常有趣。
这两个构造方法合起来的意思是:
当我们创建HandlerExecutionChain时,传入的不是一个HandlerExecutionChain对象时,我们默认是不会加入拦截器的,但是我们会加入处理器映射器里面配置的拦截器。
如果我们传入的是一个HandlerExecutionChain对象时,就会加入该对象已有的拦截器,并且也会加入处理器映射器里面的拦截器。
所以啊!我们配置Handler的时候,该Handler也可以是一个HandlerExecutionChain对象。我们可以向HandlerExecutionChain里面注入Handler和拦截器集合,注入时必须注入到interceptors数组变量里面,而不是interceptorList里面,因为interceptorList会被重新在构造方法里面赋值。
实践:通过HandlerExecutionChain对象替代Handler,实现一个Handler拥有专属的拦截器组
创建Handler:public class ItemController_Interceptor02 implements Controller{ @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println("执行ItemController_Interceptor02!!!"); return null; } }
创建拦截器:
public class Interceptor02 implements HandlerInterceptor{ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandler-----Interceptor02"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle-----Interceptor02"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion-----Interceptor02"); } }
在SpringMVC核心配置文件中进行配置:
<!-- #######################创建HandlerExecutionChain对象,并向里面注入Handler和拦截器组##################### --> <!-- 配置处理器 --> <bean id="itemContorllerHandler01" class="cn.domarvel.controller.ItemController_Interceptor02"></bean> <!-- 配置拦截器 --> <bean id="interceptor02" class="cn.domarvel.interceptor.Interceptor02"></bean> <bean id="handerExecutionChain01" class="org.springframework.web.servlet.HandlerExecutionChain"> <!-- 注入Handler,必须注入,如果为null,那么在寻找Adaptor的时候会找不到Adaptor来执行该Handler,会抛出异常!! --> <property name="handler" ref="itemContorllerHandler01"></property> <!-- 注入拦截器,拦截器可有可不有 --> <property name="interceptors" ref="interceptor02"/> </bean> <!-- 配置处理器映射器 --> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/handlerExecutionChain-handler.action">handerExecutionChain01</prop> </props> </property> </bean> <!-- ############################################################################################## -->
注意:handler必须要注入到HandlerExecutionChain对象里面,否则。。。会抛出异常!!
嗯,感觉挺好的!!但是。。。。
哦豁!!报异常了。。。
那么这种方式是不对的。不能通过无参构造创建HandlerExecutionChai对象,之后再注入参数。
那么我们是否可以继承HandlerExecutionChain,把set方法和无参构造方法添加上呢??
也就是说,我们SpringMVC核心配置文件有变!!
<!-- #######################创建HandlerExecutionChain对象,并向里面注入Handler和拦截器组##################### --> <!-- 配置处理器 --> <bean id="itemContorllerHandler01" class="cn.domarvel.controller.ItemController_Interceptor02"></bean> <!-- 配置拦截器 --> <bean id="interceptor02" class="cn.domarvel.interceptor.Interceptor02"></bean> <bean id="handerExecutionChain01" class="org.springframework.web.servlet.HandlerExecutionChain"> <!-- 注入Handler,必须注入,如果为null,那么在寻找Adaptor的时候会找不到Adaptor来执行该Handler,会抛出异常!! --> <constructor-arg name="handler" ref="itemContorllerHandler01"></constructor-arg> <!-- 注入拦截器,拦截器可有可不有 --> <constructor-arg name="interceptors"> <array> <ref bean="interceptor02"/> </array> </constructor-arg> </bean> <!-- 配置处理器映射器 --> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/handlerExecutionChain-handler.action">handerExecutionChain01</prop> </props> </property> </bean> <!-- ############################################################################################## -->
再来尝试访问下:
注意点:
当Handler(处理器)被HandlerExecutionChain替代时。拦截器组的组成由两个部分的拦截器组成。
总的拦截器=HandlerExecutionChain中的拦截器组+处理器映射器里面配置的拦截器。
前提条件:该HandlerExecutionChain对象被配置在该处理器映射器中。
HandlerExecutionChain中拦截器组的存储顺序为,先存储HandlerExecutionChain中的拦截器组,然后才是存储处理器映射器里面配置的拦截器。
嗯,非常Nice!!
继续之前之前之前的分析,目前我们讲到了这里:
当SpringMVC返回一个HandlerExecutionChain对象后。
进入applyPreHandle()方法:
在所有拦截器的applyPreHandle()方法执行完毕后,执行Handler,并且返回一个视图。
拦截器的preHandle()方法一般用来判断请求状态是否满足需要,编码是否需要调整等。
Handler执行完毕后执行postHandle()方法。该方法一般用作处理编码或者判断ModelAndView的结果是否正确,是否还需要调整。
执行所有拦截器的postHandle()方法后执行processDispatchResult()方法。
其中ModelAndView渲染的意思是,解析View,取出Model数据填充到request中,最后进行页面跳转(转发或者包含)。也就是说render()方法执行完毕后,我们客户端(浏览器)就能看到效果了。
render()方法由视图解析器实现。解析器在SpringMVC配置文件中进行配置。
最后的最后执行所有拦截器afterCompletion()方法。该步骤一般是用来释放资源用的。
至此拦截器的执行过程就讲解完毕了。
非常Nice!!!
实现拦截器的其它方法
继承HandlerInterceptorAdapter这个抽象类。该抽象类已经实现了HandlerInterceptor这个接口。相关文章推荐
- 【spring源码学习】springMVC之映射,拦截器解析,请求数据注入解析,DispatcherServlet执行过程
- springmvc的执行过程的源码分析
- yii框架源码分析之Yii::createWebApplication()->run() 执行过程分析
- hsqldb源码分析系列3 执行引擎分析 插入过程分析
- [转]jQuery源码解读---执行过程分析
- SpringMVC源码分析(3):分析ModelAndView的形成过程
- SpringMVC拦截器详解[附带源码分析]
- mysql源码分析之SQL执行过程简介
- ARM linux源码分析之init进程创建和执行过程
- [转]SpringMVC拦截器详解[附带源码分析]
- 源码分析之struts1自定义方法的使用与执行过程
- knockout源码分析之执行过程
- Hive执行过程源码分析
- Spring之SpringMVC(源码)启动初始化过程分析
- yii框架源码分析之Yii::createWebApplication()->run() 执行过程分析
- hsqldb源码分析系列3 执行引擎分析 插入过程分析
- Spark 源码分析 -- task实际执行过程
- MapReduce执行过程源码分析(一)——Job任务的提交
- zeppelin源码分析(6)——note的执行过程