SpringMVC 执行流程源码分析 
用户发出请求到前端控制器 DispatcherServlet,DispatcherServlet收到请求后,调用 HandlerMapping(处理器映射器),HandlerMapping 找到具体的处理器(通过 XML 或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给 DispatcherServlet,然后 DispatcherServlet 调用 HandlerAdpter(处理器适配器),HandlerAdpter 经过适配调用具体的 Controller/Handler 的某个方法,Controller 执行完成返回 ModelAndView 对象。HandlerAdapter 将 Controller 返回的 ModelAndView 返回给 DispatcherServlet,然后再传递给 ViewReslover(视图解析器),最后解析后返回具体 View。DispatcherServlet 根据 View 进行渲染视图(将模型数据填充至视图中),响应用户。
之所以把单个映射器、适配器、视图解析器都分离开,是为了解耦。
 
源码分析 DispatcherServlet DispatcherServlet 会拦截所有的前端请求,然后进行分发,继承了 HttpServlet。其父类 FrameworkServlet 重写了 service 方法。
RequestContextHolder 当一个请求被拦截后,进入了 service 方法中,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Override protected  void  service (HttpServletRequest request, HttpServletResponse response) 		throws  ServletException, IOException  {	 	HttpMethod httpMethod = HttpMethod.resolve(request.getMethod()); 	if  (httpMethod == HttpMethod.PATCH || httpMethod == null ) { 		processRequest(request, response); 	} 	else  { 	    		super .service(request, response); 	} } @Override protected  final  void  doPost (HttpServletRequest request, HttpServletResponse response)  throws  ServletException, IOException          processRequest(request, response); } 
发现,FrameworkServlet 覆盖了 doGet、doPOST 方法,所以是调用子类的 doGet、doPOST 方法。一般来说,框架设计中 使用 do 开头的方法是回调方法,或者是勾子方法,指的是触发某个事件时,会调用该方法 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 protected  final  void  processRequest (HttpServletRequest request, HttpServletResponse response)  throws  ServletException, IOException 	 	long  startTime = System.currentTimeMillis(); 	Throwable failureCause = null ; 	 	LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); 	LocaleContext localeContext = buildLocaleContext(request); 	 	RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); 	 	ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes); 	WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 	asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new  RequestBindingInterceptor()); 	 	 	initContextHolders(request, localeContext, requestAttributes); 	 	 	try  { 		 		doService(request, response); 	} 	 	finally  { 		 		resetContextHolders(request, previousLocaleContext, previousAttributes); 		if  (requestAttributes != null ) { 			requestAttributes.requestCompleted(); 		} 		logResult(request, response, failureCause, asyncManager); 		publishRequestHandledEvent(request, response, startTime, failureCause); 	} } 
processRequest(request, response) 的具体实现可以分为以下几步:
获取上一个请求的参数 
重新建立新的参数 
设置新的参数到 XXContextHolder, Key 为当前的线程 值为请求对象 
处理新的请求,如果出现异常,恢复 request 
发布请求处理事件 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private  void  initContextHolders (HttpServletRequest request,                                  LocaleContext localeContext,                                  RequestAttributes requestAttributes)  if  (localeContext != null ) {        LocaleContextHolder.setLocaleContext(localeContext,  this .threadContextInheritable);    } if  (requestAttributes != null ) {        RequestContextHolder.setRequestAttributes(requestAttributes,  this .threadContextInheritable);    } if  (logger.isTraceEnabled()) {        logger.trace("Bound request context to thread: "  + request);     } } 
doService 中又调用了关键方法 doDispatch,看来分发步骤应该是在 doDispatch 方法中执行的。点进去看看:看注释分析
doDispatch 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 protected  void  doDispatch (HttpServletRequest request, HttpServletResponse response)  throws  Exception 	HttpServletRequest processedRequest = request; 	 	HandlerExecutionChain mappedHandler = null ; 	boolean  multipartRequestParsed = false ; 	WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 	try  { 	    		ModelAndView mv = null ; 		Exception dispatchException = null ; 		try  { 		        		processedRequest = checkMultipart(request);     		multipartRequestParsed = (processedRequest != request);          		     		     		mappedHandler = getHandler(processedRequest);     		if  (mappedHandler == null ) {     			noHandlerFound(processedRequest, response);     			return ;     		}     		     		     		HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());          		String method = request.getMethod();     		boolean  isGet = "GET" .equals(method);     		if  (isGet || "HEAD" .equals(method)) {     			long  lastModified = ha.getLastModified(request, mappedHandler.getHandler());     			if  (new  ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {     				return ;     			}     		}     		     		if  (!mappedHandler.applyPreHandle(processedRequest, response)) {     			return ;     		}     		     		     		mv = ha.handle(processedRequest, response, mappedHandler.getHandler());          		if  (asyncManager.isConcurrentHandlingStarted()) {     			return ;     		}     		     		applyDefaultViewName(processedRequest, mv);     		     		mappedHandler.applyPostHandle(processedRequest, response, mv); 		} 		catch  (Exception ex) { 			dispatchException = ex; 		} 		catch  (Throwable err) { 			dispatchException = new  NestedServletException("Handler dispatch failed" , err); 		} 		 		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); 	} 	catch  (Exception ex) { 		triggerAfterCompletion(processedRequest, response, mappedHandler, ex); 	} 	catch  (Throwable err) { 		triggerAfterCompletion(processedRequest, response, mappedHandler, 				new  NestedServletException("Handler processing failed" , err)); 	} 	finally  { 		if  (asyncManager.isConcurrentHandlingStarted()) { 			 			if  (mappedHandler != null ) { 				mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); 			} 		} 		else  { 			 			if  (multipartRequestParsed) { 				cleanupMultipart(processedRequest); 			} 		} 	} } 
[1]getHandler(processedRequest) mappedHandler = getHandler(processedRequest); 方法中做的事情
1 2 3 4 5 6 7 8 9 10 11 protected  HandlerExecutionChain getHandler (HttpServletRequest request)  throws  Exception 	if  (this .handlerMappings != null ) { 		for  (HandlerMapping mapping : this .handlerMappings) { 			HandlerExecutionChain handler = mapping.getHandler(request); 			if  (handler != null ) { 				return  handler; 			} 		} 	} 	return  null ; } 
我们自己配的 BeanNameUrlHandlerMapping,按照 bean name 和 url 来映射 Handler。现在进入 getHandler(request) 看看做了什么,返回了一个 处理链。
getHandler(request) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public  final  HandlerExecutionChain getHandler (HttpServletRequest request)  throws  Exception               Object handler = getHandlerInternal(request);     if  (handler == null ) {     	handler = getDefaultHandler();     }     if  (handler == null ) {     	return  null ;     }          if  (handler instanceof  String) {     	String handlerName = (String) handler;     	handler = obtainApplicationContext().getBean(handlerName);     }          HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);          if  (logger.isTraceEnabled()) {     	logger.trace("Mapped to "  + handler);     }     else  if  (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {     	logger.debug("Mapped to "  + executionChain.getHandler());     }          if  (CorsUtils.isCorsRequest(request)) {     	CorsConfiguration globalConfig = this .corsConfigurationSource.getCorsConfiguration(request);     	CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);     	CorsConfiguration config = (globalConfig != null  ? globalConfig.combine(handlerConfig) : handlerConfig);     	executionChain = getCorsHandlerExecutionChain(request, executionChain, config);     }          return  executionChain; } 
可以看到 handler 对象包含以下属性。
根据后续代码的分析,发现 getHandler 方法最终返回的 HandlerExecutionChain 对象,本质上就是两个拦截器链和一个 handler。
HandlerExecutionChain 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public  class  HandlerExecutionChain  	private  static  final  Log logger = LogFactory.getLog(HandlerExecutionChain.class); 	private  final  Object handler; 	@Nullable  	private  HandlerInterceptor[] interceptors; 	@Nullable  	private  List<HandlerInterceptor> interceptorList; 	 	... } 
类中包含 handler 用于描述 映射方法的详细信息。 
HandlerInterceptor[] 数组,拦截器链条,执行 handler 前,会按照该链条执行所有拦截器的 preHandle() 方法 
List 链表,拦截器链条,执行 handler 前,会按照该链条执行所有拦截器的 preHandle() 方法  
 
[2] getHandlerAdapter(Object handler) 1 2 3 4 5 6 7 8 9 10 11 protected  HandlerAdapter getHandlerAdapter (Object handler)  throws  ServletException 	if  (this .handlerAdapters != null ) { 		for  (HandlerAdapter adapter : this .handlerAdapters) { 			if  (adapter.supports(handler)) { 				return  adapter; 			} 		} 	} 	throw  new  ServletException("No adapter for handler ["  + handler + 			"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler" ); } 
遍历适配器,看适配器中是否有可以支持 handler 的执行。supports(handler) 方法实际上就是,看 handler 是否实现了 this.handlerAdapters 中对应的 Adapter 需要实现的接口。例如:SimpleControllerHandlerAdapter 需要 handler 实现 Controller 接口。
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 
返回的 ModelAndView,view 表示路径,这里只是逻辑路径,后续方法中会为其加入前缀和后缀,编程物理路径,model 中存放所有的共享数据
[3]processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); 处理分发的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 private  void  processDispatchResult (HttpServletRequest request, HttpServletResponse response, 		@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, 		@Nullable Exception exception)  throws  Exception 	boolean  errorView = false ; 	if  (exception != null ) { 		if  (exception instanceof  ModelAndViewDefiningException) { 			logger.debug("ModelAndViewDefiningException encountered" , exception); 			mv = ((ModelAndViewDefiningException) exception).getModelAndView(); 		} 		else  { 			Object handler = (mappedHandler != null  ? mappedHandler.getHandler() : null ); 			mv = processHandlerException(request, response, handler, exception); 			errorView = (mv != null ); 		} 	} 	if  (mv != null  && !mv.wasCleared()) { 		 		render(mv, request, response); 		if  (errorView) { 			WebUtils.clearErrorRequestAttributes(request); 		} 	} 	else  { 		if  (logger.isTraceEnabled()) { 			logger.trace("No view rendering, null ModelAndView returned." ); 		} 	} 	if  (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { 		 		return ; 	} 	if  (mappedHandler != null ) { 		mappedHandler.triggerAfterCompletion(request, response, null ); 	} } 
继续往下走
render(mv, request, response); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 protected  void  render (ModelAndView mv, HttpServletRequest request, HttpServletResponse response)  throws  Exception 	 	Locale locale = 			(this .localeResolver != null  ? this .localeResolver.resolveLocale(request) : request.getLocale()); 	response.setLocale(locale); 	View view;  	String viewName = mv.getViewName(); 	if  (viewName != null ) { 		 		view = resolveViewName(viewName, mv.getModelInternal(), locale, request); 		if  (view == null ) { 			throw  new  ServletException("Could not resolve view with name '"  + mv.getViewName() + 					"' in servlet with name '"  + getServletName() + "'" ); 		} 	} 	else  { 		view = mv.getView(); 		if  (view == null ) { 			throw  new  ServletException("ModelAndView ["  + mv + "] neither contains a view name nor a "  + 					"View object in servlet with name '"  + getServletName() + "'" ); 		} 	} 	if  (logger.isTraceEnabled()) { 		logger.trace("Rendering view ["  + view + "] " ); 	} 	try  { 		if  (mv.getStatus() != null ) { 			response.setStatus(mv.getStatus().value()); 		} 		 		view.render(mv.getModelInternal(), request, response); 	} 	catch  (Exception ex) { 		if  (logger.isDebugEnabled()) { 			logger.debug("Error rendering view ["  + view + "]" , ex); 		} 		throw  ex; 	} } 
view.render(mv.getModelInternal(), request, response); 1 2 3 4 5 6 7 8 9 10 11 12 13 public  void  render (@Nullable Map<String, ?> model, HttpServletRequest request, 		HttpServletResponse response)  throws  Exception 	if  (logger.isDebugEnabled()) { 		logger.debug("View "  + formatViewName() + 				", model "  + (model != null  ? model : Collections.emptyMap()) + 				(this .staticAttributes.isEmpty() ? ""  : ", static attributes "  + this .staticAttributes)); 	} 	 	Map<String, Object> mergedModel = createMergedOutputModel(model, request, response); 	prepareResponse(request, response); 	renderMergedOutputModel(mergedModel, getRequestToExpose(request), response); } 
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response); Output,可以看出,这一步就是将数据和视图输出了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 protected  void  renderMergedOutputModel ( 		Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)  throws  Exception 	exposeModelAsRequestAttributes(model, request); 	exposeHelpers(request); 	String dispatcherPath = prepareForRendering(request, response); 	 	RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath); 	if  (rd == null ) { 		throw  new  ServletException("Could not get RequestDispatcher for ["  + getUrl() + 				"]: Check that the corresponding file exists within your web application archive!" ); 	} 	if  (useInclude(request, response)) { 		response.setContentType(getContentType()); 		if  (logger.isDebugEnabled()) { 			logger.debug("Including ["  + getUrl() + "]" ); 		} 		rd.include(request, response); 	} 	else  { 		if  (logger.isDebugEnabled()) { 			logger.debug("Forwarding to ["  + getUrl() + "]" ); 		} 		 		rd.forward(request, response); 	} } 
至此,就完成了整个请求在 SpringMVC 中执行的整个过程。 
手写 springMVC 框架 只编写一个 Servlet 去进行请求分发,后台只需要编写普通的处理器去处理不同的请求。
接收客户端发送过来的请求 
根据请求URL查找对应的请求处理类 
调用请求处理类的方法处理请求 
处理响应结果 
 
1 2 3 4 5 6 7 8 public  class  DispatcherServlet  	public  void  doDispatch ()   		 		if  ("/user" .equals(url)) { 			 		} 	} } 
url-parttern 的配置方式:完整路径/xxx,/,/*,*.后缀
 
主流程 
浏览器输入 /query URI 时,http://localhost/query?id=1&username=ammar 
程序会进入我们在 web.xml 中配置的 servlet 
 
web.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?xml version="1.0" encoding="UTF-8"?> <web-app  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"  xmlns ="http://java.sun.com/xml/ns/javaee"  xsi:schemaLocation ="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  version ="2.5" >   <servlet >      <servlet-name > DispatcherServlet</servlet-name >      <servlet-class > cn.lizhaoloveit.springmvc.servlet.DispatchServlet</servlet-class >           <init-param >      	     	<param-name > contextConfigLocation</param-name >      	<param-value > classpath:springmvc.xml</param-value >      </init-param >    </servlet >    <servlet-mapping >        <servlet-name > DispatcherServlet</servlet-name >        <url-pattern > /</url-pattern >    </servlet-mapping >  </web-app > 
DispatcherServlet 
此时,使用了抽象模板的设计模式来构建 DispatcherServlet,创建抽象类 AbstractHttpServlet 继承 HttpServlet 
 
1 2 3 4 5 6 7 8 9 10 11 public  abstract  class  AbstractHttpServlet  extends  HttpServlet      @Override      protected  void  doGet (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException          doDispatch(req, resp);     }     @Override      protected  void  doPost (HttpServletRequest req, HttpServletResponse resp)  throws  ServletException, IOException          doGet(req, resp);     }     public  abstract  void  doDispatch (HttpServletRequest request, HttpServletResponse response)  } 
使用钩子方法 doDispatch 处理所有的请求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public  class  DispatchServlet  extends  AbstractHttpServlet      private  List<HandlerMapping> handlerMappings = new  ArrayList<>();     private  List<HandlerAdapter> handlerAdapters = new  ArrayList<>();     @Override      public  void  init (ServletConfig config)           String contextConfigLocation = config.getInitParameter("contextConfigLocation" );         BeanFactory beanFactory = new  DefaultListableBeanFactory(contextConfigLocation);         beanFactory.getBeanNamesByType(Object.class);          handlerMappings = beanFactory.getBeansByType(HandlerMapping.class);         handlerAdapters = beanFactory.getBeansByType(HandlerAdapter.class);     }     @Override      public  void  doDispatch (HttpServletRequest request, HttpServletResponse response)                    Object handler = null ;         for  (HandlerMapping handlerMapping : handlerMappings) {             Object handlerTemp = handlerMapping.getHandler(request);             if  (handlerTemp != null ) handler = handlerTemp;         }                  HandlerAdapter ha = null ;         for  (HandlerAdapter handlerAdapter : handlerAdapters) {             if  (handlerAdapter.support(handler)) {                 ha = handlerAdapter;             }         }         try  {             ha.handleRequest(handler, request, response);         } catch  (Exception e) {             e.printStackTrace();         }     } } 
此时,由于处理请求的处理器多种多样,无法用一个接口来概括所有的处理方式,所以采用了策略设计模式,用我们预先写好的 request 和 handler 的映射器 HandlerRequestMapping 去匹配请求,如果可以找到映射。就可以找到处理器。 
 
HandlerMapping 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public  class  RequestMappingHandlerMapping  implements  HandlerMapping , BeanFactoryAware           private  Map<String, HandlerMethod> urlHandlerMethodMap = new  HashMap<>();     private  BeanFactory beanFactory;               public  void  setBeanFactory (BeanFactory beanFactory)           this .beanFactory = beanFactory;     }     public  void  initMethod ()                    List<String> beanNames = beanFactory.getBeanNamesByType(Object.class);         for  (String beanName : beanNames) {             Map<String, BeanDefinition> beanDefinitions = beanFactory.getBeanDefiitions();             BeanDefinition beanDefinition = beanDefinitions.get(beanName);             String beanClassName = beanDefinition.getBeanClassName();             try  {                 Class<?> clazz = Class.forName(beanClassName);                                  if  (clazz.isAnnotationPresent(Controller.class)) {                     Method[] methods = clazz.getDeclaredMethods();                     for  (Method method : methods) {                         if  (method.isAnnotationPresent(RequestMapping.class)) {                             RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);                             String url = requestMapping.value();                             HandlerMethod handlerMethod = new  HandlerMethod(method, beanFactory.getBean(beanName));                             urlHandlerMethodMap.put(url, handlerMethod);                         }                     }                 }             } catch  (ClassNotFoundException e) {                 e.printStackTrace();             }         }     }     @Override      public  Object getHandler (HttpServletRequest request)           String uri = request.getRequestURI();         return  urlHandlerMethodMap.get(uri);     } } 
HandlerMapping 类在初始化时就已经将项目中所有的映射关系保存在 Map 中了,在拿到请求后,只需要判断 Map 中是否有 url key。
HandlerAdapter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 public  class  RequestMappingHandlerAdapter  implements  HandlerAdapter      @Override      public  boolean  support (Object handler)           return  handler instanceof  HandlerMethod;     }     @Override      public  void  handleRequest (Object handler, HttpServletRequest request, HttpServletResponse response)  throws  Exception          HandlerMethod handlerMethod = (HandlerMethod) handler;         Method method = handlerMethod.getMethod();         Object object = handlerMethod.getHandler();                  Map<String, String[]> paramMap = request.getParameterMap();         List<Object> args = new  ArrayList<>();         Parameter[] parameters = method.getParameters();         for  (Parameter parameter : parameters) {                          String name = parameter.getName();             Class<?> type = parameter.getType();             String[] value = paramMap.get(name);             if  (value == null ) {                 args.add(null );                 continue ;             }             if  (type == Integer.class) {                 args.add(Integer.valueOf(value[0 ]));             } else  if  (type == String.class) {                 args.add(value[0 ]);             }         }         Object[] argsObj = args.toArray();                  Object returnValue = method.invoke(object, argsObj);                  if  (method.isAnnotationPresent(ResponseBody.class)) {             if  (returnValue instanceof  String) {                 response.setContentType("text/plain;charset=utf8" );                 response.getWriter().write(returnValue.toString());             } else  if  (returnValue instanceof  Map) {                 response.setContentType("application/json;charset=utf8" );                 String s = JsonUtils.object2Json(returnValue);                 response.getWriter().write(s);             }         } else  {                      }     } } 
Adapter 是 springmvc 框架中处理器输入输出的中转站。将数据按规则过滤和处理。
最终的效果:
url: http://localhost/query?id=3&username=ammar 
1 2 3 4 {     "id" : 3 ,     "username" : "ammar"  } 
代码地址:手写springmvc框架