publicclassDispatcherServletextendsFrameworkServlet{protectedvoiddoDispatch(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{HttpServletRequestprocessedRequest=request;HandlerExecutionChainmappedHandler=null;booleanmultipartRequestParsed=false;/* TODO
预处理:
1. 获取HandlerMethod和过滤器链的包装类(url-hanlderMethod映射):HandlerExecutionChain,里面包含了handlerMethod对象
2. 根据handlerMethod对象,找到合适的HandlerAdapter对象,这里用到了策略模式
调用链:
1. 前置拦截,正向遍历调用,若有返回false,则调用后置处理,返回。
interceptor.preHandle(request, response, this.handler)
triggerAfterCompletion(request, response, null);
2. 根据HandlerAdapter获取真正的处理类,执行:((Controller) handler).handleRequest(request, response)
3. 中置拦截,反向遍历调用。 interceptor.postHandle(request, response, this.handler, mv);
4. 视图渲染,在视图渲染之后,会在视图渲染方法中调用后置处理。
render(mv, request, response);
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
*/// 异步管理WebAsyncManagerasyncManager=WebAsyncUtils.getAsyncManager(request);try{ModelAndViewmv=null;ExceptiondispatchException=null;try{// 文件上传processedRequest=checkMultipart(request);multipartRequestParsed=(processedRequest!=request);// TODO 这个方法很重要,重点看 获取封装了 handlerMethod、拦截器的执行链封装 HandlerExecutionChain。// Determine handler for the current request.mappedHandler=getHandler(processedRequest);if(mappedHandler==null){noHandlerFound(processedRequest,response);return;}// TODO 获取跟HandlerMethod匹配的HandlerAdapter对象// Determine handler adapter for the current request.HandlerAdapterha=getHandlerAdapter(mappedHandler.getHandler());// Process last-modified header, if supported by the handler.Stringmethod=request.getMethod();booleanisGet="GET".equals(method);if(isGet||"HEAD".equals(method)){longlastModified=ha.getLastModified(request,mappedHandler.getHandler());if(newServletWebRequest(request,response).checkNotModified(lastModified)&&isGet){return;}}// TODO 前置过滤器,如果为false则直接返回if(!mappedHandler.applyPreHandle(processedRequest,response)){return;}// TODO 调用到Controller具体方法,核心方法调用,重点看看// Actually invoke the handler.mv=ha.handle(processedRequest,response,mappedHandler.getHandler());if(asyncManager.isConcurrentHandlingStarted()){return;}applyDefaultViewName(processedRequest,mv);// TODO 执行中置拦截mappedHandler.applyPostHandle(processedRequest,response,mv);}catch(Exceptionex){dispatchException=ex;}catch(Throwableerr){// As of 4.3, we're processing Errors thrown from handler methods as well,// making them available for @ExceptionHandler methods and other scenarios.dispatchException=newNestedServletException("Handler dispatch failed",err);}// TODO 处理结果,这里执行了后置拦截。在前面的流程里捕获了业务方法执行过程中抛出的异常。// 如果上面的流程中抛出了异常,则dispatchException一定有值。processDispatchResult(processedRequest,response,mappedHandler,mv,dispatchException);}catch(Exceptionex){triggerAfterCompletion(processedRequest,response,mappedHandler,ex);}catch(Throwableerr){triggerAfterCompletion(processedRequest,response,mappedHandler,newNestedServletException("Handler processing failed",err));}finally{if(asyncManager.isConcurrentHandlingStarted()){// Instead of postHandle and afterCompletionif(mappedHandler!=null){mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest,response);}}else{// Clean up any resources used by a multipart request.if(multipartRequestParsed){cleanupMultipart(processedRequest);}}}}}
publicabstractclassAbstractHandlerMappingextendsWebApplicationObjectSupportimplementsHandlerMapping,Ordered,BeanNameAware{publicfinalHandlerExecutionChaingetHandler(HttpServletRequestrequest)throwsException{// TODO 获取 HandlerMethodObjecthandler=getHandlerInternal(request);if(handler==null){handler=getDefaultHandler();}if(handler==null){returnnull;}// Bean name or resolved handler?if(handlerinstanceofString){StringhandlerName=(String)handler;handler=obtainApplicationContext().getBean(handlerName);}// TODO 将 handlerMethod,包装到 HandlerExecutionChain 中。HandlerExecutionChainexecutionChain=getHandlerExecutionChain(handler,request);// 省略无关代码...returnexecutionChain;}}
publicclassHandlerMethod{publicHandlerMethodcreateWithResolvedBean(){Objecthandler=this.bean;// 最初这个 bean 成员变量,只是设置了一个 beanName,因此它是字符串类型的,执行到这里会调用 getBean(),将真正的实例设置到这里。// 如果已经设置过了,bean就不是字符串类型了,就不会进这个 if 语句。if(this.beaninstanceofString){Assert.state(this.beanFactory!=null,"Cannot resolve bean name without BeanFactory");StringbeanName=(String)this.bean;handler=this.beanFactory.getBean(beanName);}returnnewHandlerMethod(this,handler);}}
publicclassDispatcherServletextendsFrameworkServlet{protectedHandlerAdaptergetHandlerAdapter(Objecthandler)throwsServletException{// 根据handlerMethod对象,找到合适的HandlerAdapter对象,这里是典型的的策略模式// 遍历所有的 handlerAdapters,并调用其 supports(),如果有 adapter 支持这个 handlerMethod,就返回这个 adapter。if(this.handlerAdapters!=null){for(HandlerAdapteradapter:this.handlerAdapters){if(adapter.supports(handler)){returnadapter;}}}thrownewServletException("No adapter for handler ["+handler+"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");}}
publicclassExceptionHandlerExceptionResolverextendsAbstractHandlerMethodExceptionResolverimplementsApplicationContextAware,InitializingBean{protectedModelAndViewdoResolveHandlerMethodException(HttpServletRequestrequest,HttpServletResponseresponse,@NullableHandlerMethodhandlerMethod,Exceptionexception){// TODO 获取异常处理方法ServletInvocableHandlerMethodexceptionHandlerMethod=getExceptionHandlerMethod(handlerMethod,exception);if(exceptionHandlerMethod==null){returnnull;}// 设置参数解析器和返回值处理器if(this.argumentResolvers!=null){exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);}if(this.returnValueHandlers!=null){exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);}// 省略部分代码...Throwablecause=exception.getCause();if(cause!=null){// 异常处理方法的执行。// Expose cause as provided argument as wellexceptionHandlerMethod.invokeAndHandle(webRequest,mavContainer,exception,cause,handlerMethod);}// 省略部分代码...}}
publicclassExceptionHandlerExceptionResolverextendsAbstractHandlerMethodExceptionResolverimplementsApplicationContextAware,InitializingBean{protectedServletInvocableHandlerMethodgetExceptionHandlerMethod(@NullableHandlerMethodhandlerMethod,Exceptionexception){Class<?>handlerType=null;// 获取异常处理方法,这里使用了缓存,也就是只会查找一次。if(handlerMethod!=null){// Local exception handler methods on the controller class itself.// To be invoked through the proxy, even in case of an interface-based proxy.handlerType=handlerMethod.getBeanType();ExceptionHandlerMethodResolverresolver=this.exceptionHandlerCache.get(handlerType);if(resolver==null){// ExceptionHandlerMethodResolver定义了对注解@ExceptionHandler的支持// 查找@ControllerAdvice标注的处理类中,标注有 @ExceptionHandler 的方法,并将注解中配置的 Exception类型与方法的反射对象// 映射关系封装缓存起来。如果一个controller中抛出了异常,就可以根据这个异常从异常处理类中找到这个处理方法了。resolver=newExceptionHandlerMethodResolver(handlerType);this.exceptionHandlerCache.put(handlerType,resolver);}Methodmethod=resolver.resolveMethod(exception);if(method!=null){returnnewServletInvocableHandlerMethod(handlerMethod.getBean(),method);}// For advice applicability check below (involving base packages, assignable types// and annotation presence), use target class instead of interface-based proxy.if(Proxy.isProxyClass(handlerType)){handlerType=AopUtils.getTargetClass(handlerMethod.getBean());}}// 省略部分代码...returnnull;}}
publicclassServletInvocableHandlerMethodextendsInvocableHandlerMethod{publicvoidinvokeAndHandle(ServletWebRequestwebRequest,ModelAndViewContainermavContainer,Object...providedArgs)throwsException{// TODO 重点:具体方法调用逻辑ObjectreturnValue=invokeForRequest(webRequest,mavContainer,providedArgs);// 省略部分代码...// TODO 使用返回值处理器,对返回值进行处理this.returnValueHandlers.handleReturnValue(returnValue,getReturnValueType(returnValue),mavContainer,webRequest);// 省略部分代码...}}
首先反射调用异常处理方法,然后调用返回值处理。
反射调用逻辑:
1
2
3
4
5
6
7
8
9
10
publicclassInvocableHandlerMethodextendsHandlerMethod{publicObjectinvokeForRequest(NativeWebRequestrequest,@NullableModelAndViewContainermavContainer,Object...providedArgs)throwsException{// TODO 重点:获取参数数组Object[]args=getMethodArgumentValues(request,mavContainer,providedArgs);// TODO 方法的反射执行returndoInvoke(args);}}
publicclassHandlerMethodReturnValueHandlerCompositeimplementsHandlerMethodReturnValueHandler{publicvoidhandleReturnValue(@NullableObjectreturnValue,MethodParameterreturnType,ModelAndViewContainermavContainer,NativeWebRequestwebRequest)throwsException{// TODO 查找返回值处理器,策略模式的一种运用HandlerMethodReturnValueHandlerhandler=selectHandler(returnValue,returnType);// 如果不存在返回值处理器,则跑出异常if(handler==null){thrownewIllegalArgumentException("Unknown return value type: "+returnType.getParameterType().getName());}// 对返回值进行处理handler.handleReturnValue(returnValue,returnType,mavContainer,webRequest);}}