spring mvc 源码要点1
前置 : 版本4.1.2
请求如何定位到对应的处理方法?
a. 入口 DispatcherServlet的 doService方法
doDispatch(request,response);
b. 解析路径
protectedvoiddoDispatch(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{HttpServletRequestprocessedRequest=request;HandlerExecutionChainmappedHandler=null;booleanmultipartRequestParsed=false;WebAsyncManagerasyncManager=WebAsyncUtils.getAsyncManager(request);try{ModelAndViewmv=null;ExceptiondispatchException=null;try{processedRequest=checkMultipart(request);multipartRequestParsed=(processedRequest!=request);//Determinehandlerforthecurrentrequest.mappedHandler=getHandler(processedRequest);----------------步骤1if(mappedHandler==null||mappedHandler.getHandler()==null){noHandlerFound(processedRequest,response);return;}//Determinehandleradapterforthecurrentrequest.HandlerAdapterha=getHandlerAdapter(mappedHandler.getHandler());---------步骤2//Processlast-modifiedheader,ifsupportedbythehandler.Stringmethod=request.getMethod();booleanisGet="GET".equals(method);if(isGet||"HEAD".equals(method)){longlastModified=ha.getLastModified(request,mappedHandler.getHandler());if(logger.isDebugEnabled()){logger.debug("Last-Modifiedvaluefor["+getRequestUri(request)+"]is:"+lastModified);}if(newServletWebRequest(request,response).checkNotModified(lastModified)&&isGet){return;}}if(!mappedHandler.applyPreHandle(processedRequest,response)){return;}//Actuallyinvokethehandler.mv=ha.handle(processedRequest,response,mappedHandler.getHandler());-----步骤3if(asyncManager.isConcurrentHandlingStarted()){return;}applyDefaultViewName(request,mv);mappedHandler.applyPostHandle(processedRequest,response,mv);}catch(Exceptionex){dispatchException=ex;}processDispatchResult(processedRequest,response,mappedHandler,mv,dispatchException);}catch(Exceptionex){triggerAfterCompletion(processedRequest,response,mappedHandler,ex);}catch(Errorerr){triggerAfterCompletionWithError(processedRequest,response,mappedHandler,err);}finally{if(asyncManager.isConcurrentHandlingStarted()){//InsteadofpostHandleandafterCompletionif(mappedHandler!=null){mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest,response);}}else{//Cleanupanyresourcesusedbyamultipartrequest.if(multipartRequestParsed){cleanupMultipart(processedRequest);}}}}
步骤1,点入内部,最终在AbstractHandlerMethodMapping的lookupHandlerMethod找到匹配方法
先完整匹配url,不行则正则匹配
注意步骤1中 返回的是HandlerExecutionChain , 在getHandler里同时也放入了拦截器链
步骤2 找到合适的处理请求的适配器
debug 得到是RequestMappingHandlerAdapter
步骤3 RequestMappingHandlerAdapter的handler在AbstractHandlerMethodAdapter类种
publicfinalModelAndViewhandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{returnhandleInternal(request,response,(HandlerMethod)handler);
里面的复杂逻辑目前不关心,只关注如何调用实际的方法
3. 返回值的处理
RequestMappingHandlerAdapter的invokeHandleMethod方法中,找到
requestMappingMethod.invokeAndHandle(webRequest,mavContainer);--》进入--》ObjectreturnValue=invokeForRequest(webRequest,mavContainer,providedArgs);
这里方法里包含了我们在controller里写的方法:
publicfinalObjectinvokeForRequest(NativeWebRequestrequest,ModelAndViewContainermavContainer,Object...providedArgs)throwsException{Object[]args=getMethodArgumentValues(request,mavContainer,providedArgs);if(logger.isTraceEnabled()){StringBuildersb=newStringBuilder("Invoking[");sb.append(getBeanType().getSimpleName()).append(".");sb.append(getMethod().getName()).append("]methodwitharguments");sb.append(Arrays.asList(args));logger.trace(sb.toString());}ObjectreturnValue=invoke(args);if(logger.isTraceEnabled()){logger.trace("Method["+getMethod().getName()+"]returned["+returnValue+"]");}returnreturnValue;}
回到invokeAndHandle方法,看这句话:
this.returnValueHandlers.handleReturnValue(returnValue,getReturnValueType(returnValue),mavContainer,webRequest);
RequestResponseBodyMethodProcessor 负责处理
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。