我是靠谱客的博主 舒适大地,最近开发中收集的这篇文章主要介绍dispatch类 java_6、SpringMVC源码分析(1):分析DispatcherServlet.doDispatch方法,了解总体流程...,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1 protected voiddoDispatch(HttpServletRequest request,2 HttpServletResponse response) throwsException {3

4 //processedRequest是经过checkMultipart方法处理过的request请求

5 HttpServletRequest processedRequest =request;6 /**

7 * Handler execution chain, consisting of handler object and any handler8 * interceptors. Returned by HandlerMapping's HandlerMapping.getHandler9 * method. 看看HandlerExecutionChain类的属性就很清楚了:10 *11 public class HandlerExecutionChain {12

13 private final Object handler; //这个就是和该请求对应的handler处理方法14

15 //里面记录了所有的(any handler interceptors)和该请求相关的拦截器16 private HandlerInterceptor[] interceptors;17

18 private List interceptorList;19

20 private int interceptorIndex = -1;21

22 //...23 }24 *25 */

26 HandlerExecutionChain mappedHandler = null;27 boolean multipartRequestParsed = false;28

29 WebAsyncManager asyncManager =WebAsyncUtils.getAsyncManager(request);30

31 try{32 ModelAndView mv = null;33 Exception dispatchException = null;34

35 try{36 processedRequest =checkMultipart(request);37 multipartRequestParsed = (processedRequest !=request);38

39 //Determine handler for the current request.Return a handler40 //and any interceptors for this request.

41 /*

42 * 得到的mappedHandler包含一个请求的handler处理方法以及与该请求相关的所有拦截器43 *44 * DispatcherServlet.getHandler方法会在底层调用HandlerMapping.getHandler方法45 * ,这个方法中会遍 历DispatcherServlet中的private List46 * handlerMappings链表,找到能够处理当前 request请求的第一个HandlerMapping实例并返回:47 *48 protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {49 for (HandlerMapping hm : this.handlerMappings) {50 HandlerExecutionChain handler = hm.getHandler(request);51 if (handler != null) {52 return handler;53 }54 }55 return null;56 }57 *58 */

59 mappedHandler =getHandler(processedRequest);60 //如果没有找到和该请求相对应的mappedHandler,那么就会直接返回,并应答noHandlerFound异常

61 if (mappedHandler == null || mappedHandler.getHandler() == null) {62 noHandlerFound(processedRequest, response);63 return;64 }65

66 //Determine handler adapter for the current request.

67 /*

68 * HandlerAdapter: 它是一个接口public interface HandlerAdapter69 * 看看源码上的说明:The DispatcherServlet accesses all installed70 * handlers through this interface, meaning that it does not71 * contain code specific to any handler type.72 *73 * 从后面的源码看出,在使用@RequestMapping注解标注handler方法的时候,获取到的是HandlerAdapter的74 * RequestMappingHandlerAdapter实现类的一个对象。75 *76 * 可以看看DispatcherServlet.getHandlerAdapter方法的定义,这个对理解上回很有帮助,我们会发现77 * ,getHandlerAdapter 方法和上面提到的getHandler方法一样都是寻找第一个可用的作为返回结果:78 *79 *80 protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {81 //this.handlerAdapters的定义是 private List handlerAdapters82 for (HandlerAdapter ha : this.handlerAdapters) {83 if (ha.supports(handler)) {84 return ha;85 }86 }87 throw new ServletException("No adapter for handler [" + handler +88 "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");89 }90 *91 */

92 HandlerAdapter ha =getHandlerAdapter(mappedHandler93 .getHandler());94

95 //Process last-modified header, if supported by the handler.

96 String method =request.getMethod();97 boolean isGet = "GET".equals(method);98 if (isGet || "HEAD".equals(method)) {99 long lastModified =ha.getLastModified(request,100 mappedHandler.getHandler());101 if(logger.isDebugEnabled()) {102 logger.debug("Last-Modified value for ["

103 + getRequestUri(request) + "] is: "

104 +lastModified);105 }106 if (newServletWebRequest(request, response)107 .checkNotModified(lastModified) &&isGet) {108 return;109 }110 }111

112 //Apply preHandle methods of registered interceptors.

113 /*

114 * 会调用所有注册拦截器的preHandle方法,如果preHandle方法的返回结果为true,则会继续执行下面的程序,115 * 否则会直接返回。116 *117 * 分析一下HandlerExecutionChain.applyPreHandle方法的源码 :118 boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {119 //从上面的HandlerExecutionChain定义处可以看见有个interceptors,还有一个interceptorList。不知道有什么区别??!120 HandlerInterceptor[] interceptors = getInterceptors();121 //如果已经注册有拦截器,则遍历拦截器122 if (!ObjectUtils.isEmpty(interceptors)) {123 for (int i = 0; i < interceptors.length; i++) {124 HandlerInterceptor interceptor = interceptors[i];125 //如果注册拦截器的preHandle方法返回一个false,则该applyPreHandle方法就会返回false,从而在doDispatcher中的代码就不会往下执行了126 if (!interceptor.preHandle(request, response, this.handler)) {127

128 //这个方法要注意,它会调用所有已经成功执行的拦截器的afterCompletion方法,而且是反序调用的过程,可以分析triggerAfterCompletion129 //的源代码,主要是利用interceptorIndex反减的方式实现的。下面是源码的英文注释:130 //Trigger afterCompletion callbacks on the mapped HandlerInterceptors.131 //Will just invoke afterCompletion for all interceptors whose preHandle invocation132 //has successfully completed and returned true.133 triggerAfterCompletion(request, response, null);134 return false;135 }136 //没成功执行一个拦截器的preHandle方法,其interceptorIndex就会增加1;原始值为-1。137 this.interceptorIndex = i;138 }139 }140 return true;141 }142 *143 *144 * 顺带看看triggerAfterCompletion的源代码,很容易理解为什么拦截器的afterCompletion方法是反序执行的:145 * void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)146 throws Exception {147

148 HandlerInterceptor[] interceptors = getInterceptors();149 if (!ObjectUtils.isEmpty(interceptors)) {150 for (int i = this.interceptorIndex; i >= 0; i--) {151 HandlerInterceptor interceptor = interceptors[i];152 try {153 interceptor.afterCompletion(request, response, this.handler, ex);154 }155 catch (Throwable ex2) {156 logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);157 }158 }159 }160 }161 *162 *163 */

164 if (!mappedHandler.applyPreHandle(processedRequest, response)) {165 return;166 }167

168 //Actually invoke the handler.

169 /*

170 * 在这个函数里面会真正的执行request请求相对于的handler方法,可以想象:在真正调用方法之前还会有很多的171 * 先前处理。在这里仅仅是分析出大概的代码执行流程,其细节的部分在后面的单独模块源码分析的时候做详细的讲解。172 * 上面讲解到HandlerAdapter是一个接口:public interface HandlerAdapter,那么必然会有很多173 * 中实现类,在采用注解@RequstMapping的方式标注handler的情况下,ha.handle方法会在底层调用具体的174 * HandlerAdapter类实现方法RequestMappingHandlerAdapter.handleInternal175 *176 * 分析一下RequestMappingHandlerAdapter.handleInternal的源代码:177 protected ModelAndView handleInternal(HttpServletRequest request,178 HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {179 //好像是看control的类定义处是否使用了@SessionAttributes注解,checkAndPrepare方法有什么作用???180 if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {181 // Always prevent caching in case of session attribute management.182 checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);183 }184 else {185 // Uses configured default cacheSeconds setting.186 checkAndPrepare(request, response, true);187 }188

189 // Execute invokeHandlerMethod in synchronized block if required.190 // 这里是个值得注意的地方,synchronizeOnSession的值默认为false,如果通过某个方法使得其为true,那么request对应的handler191 // 将会被放在同步快中进行处理。在什么时机下,使用什么方法才能将其设置为true呢???192 if (this.synchronizeOnSession) {193 HttpSession session = request.getSession(false);194 if (session != null) {195 Object mutex = WebUtils.getSessionMutex(session);196 // 将handler放在同步块中处理197 synchronized (mutex) {198 return invokeHandleMethod(request, response, handlerMethod);199 }200 }201 }202 //在invokeHandleMethod中会①将所有标注有@ModelAttrib的方法都执行一遍,②调用invokeAndHandle(webRequest, mavContainer)203 //方法,在这里面调用handler方法,③最后调用getModelAndView(mavContainer, modelFactory, webRequest)方法的到ModelAndView。204 //invokeHandleMethod这个方法还有很多东西要分析,留在后面。205 //从上面的③我们可以看出,无论handler采用哪种模型化处理方式,最后都是将结果转化为ModelAndView206 return invokeHandleMethod(request, response, handlerMethod);207 }208 */

209 mv =ha.handle(processedRequest, response,210 mappedHandler.getHandler());211

212 if(asyncManager.isConcurrentHandlingStarted()) {213 return;214 }215

216 applyDefaultViewName(request, mv);217 /*

218 * 调用request相关的拦截器的postHandle方法,注意,这个也是反序调用的。看看源代码:219 *220 void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {221 HandlerInterceptor[] interceptors = getInterceptors();222 if (!ObjectUtils.isEmpty(interceptors)) {223 //注意,这里也是反序执行,而且是所有成功执行了的postHandle拦截器224 for (int i = interceptors.length - 1; i >= 0; i--) {225 HandlerInterceptor interceptor = interceptors[i];226 //这里传入的参数中有mv,也就是说,我们是有办法在拦截器的postHandle方法中修改已经返回的mv227 interceptor.postHandle(request, response, this.handler, mv);228 }229 }230 }231 */

232 mappedHandler.applyPostHandle(processedRequest, response, mv);233 } catch(Exception ex) {234 dispatchException =ex;235 }236 processDispatchResult(processedRequest, response, mappedHandler,237 mv, dispatchException);238 } catch(Exception ex) {239 triggerAfterCompletion(processedRequest, response, mappedHandler,240 ex);241 } catch(Error err) {242 triggerAfterCompletionWithError(processedRequest, response,243 mappedHandler, err);244 } finally{245 if(asyncManager.isConcurrentHandlingStarted()) {246 //Instead of postHandle and afterCompletion

247 if (mappedHandler != null) {248 mappedHandler.applyAfterConcurrentHandlingStarted(249 processedRequest, response);250 }251 } else{252 //Clean up any resources used by a multipart request.

253 if(multipartRequestParsed) {254 cleanupMultipart(processedRequest);255 }256 }257 }258 }

最后

以上就是舒适大地为你收集整理的dispatch类 java_6、SpringMVC源码分析(1):分析DispatcherServlet.doDispatch方法,了解总体流程...的全部内容,希望文章能够帮你解决dispatch类 java_6、SpringMVC源码分析(1):分析DispatcherServlet.doDispatch方法,了解总体流程...所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部