SSM|SpringMVC运行流程 源码分析

本文会分析一下SpringMVC执行的流程,以及源码分析底层实现的原理 SpringMVC流程 SSM|SpringMVC运行流程 源码分析
文章图片

SSM|SpringMVC运行流程 源码分析
文章图片

SSM|SpringMVC运行流程 源码分析
文章图片

根据以上SpringMVC工作原理图,对其工作流程作如下总结

  1. 用户发送请求至前端控制器DispatcherServlet。
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。
  3. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
  4. DispatcherServlet调用HandlerAdapter处理器适配器。
  5. HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
  6. Controller执行完成返回ModelAndView。
  7. HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
  9. ViewReslover解析后返回具体View。
  10. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
  11. DispatcherServlet响应用户。
SpringMVC底层代码流程图: SSM|SpringMVC运行流程 源码分析
文章图片

SpringMVC底层核心代码块分析
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 { // 1、检查文件上传请求 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. 决定当前请求 用哪个处理器 // 2、根据当前请求 决定哪个类来处理 mappedHandler = getHandler(processedRequest); // 3、如果没有找到哪个处理器(控制器) 可以处理请求抛异常 if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; }// Determine handler adapter for the current request.决定当前请求 用哪个适配器 // 4、拿到能执行这个类的所有方法的适配器(反射工具) AnnotationMethodHandlerAdapter(注解方法的适配器) HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } }if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; }// Actually invoke the handler. // 5、适配器来执行目标方法:将目标方法完成后的返回值作为视图名 设置保存在ModelAndView中 // 目标方法无论怎么写,最终适配器执行完成以后 都会将执行后的信息封装成ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } // 使用默认的视图名请求的地址是什么 视图名就是什么 applyDefaultViewName(request, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } // 6、根据方法最终执行完成后封装的ModelAndView;转发到对应的页面,而且ModelAndView可以从请求域中获取 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Error err) { triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }

底层方法执行流程: 【SSM|SpringMVC运行流程 源码分析】? 1、所有的请求过来DispatcherServlet收到请求
? 2、调用doDispatch()方法进行处理
  • 1)、getHandler() : 根据当前请求地址找到能处理这个请求的目标处理器类(处理器)
    ? 根据当前请求在HanlderMapping中找到这个请求的映射信息,获取到目标处理器类
  • 2)、getHandlerAdapter() : 根据当前处理器类获取到能执行这个处理器方法的适配器
    根据当前处理器类,找到当前类的HandlerAdapter(适配器)
  • 3)、使用刚才获取的适配器执行目标方法(AnnotationMethodHandlerAdapter)执行目标方法 ? -
  • 4)、目标方法执行后会返回一个ModelAndView对象 ? -
  • 5)、根据ModelAndView的信息转发具体的页面,并可以在请求与中取出ModelAndView中的模型数据
3、getHandler()细节:如何根据当前请求就能找到哪个类能来处理
  • getHandler() 会返回目标处理器类的执行链 ?
  • handlerMappings 处理器映射: 里面保存了每一个处理器能处理的那些请求的映射信息 ?
  • handlerMap: ioc容器启动创建Controller对象的时候扫描每个处理器都能处理什么请求,保存在HandlerMapping的handlerMap属性中,下次请求过来 就来看哪个handlerMapping中有这个请求映射信息就行了
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { for (HandlerMapping hm : this.handlerMappings) { if (logger.isTraceEnabled()) { logger.trace( "Testing handler map [" + hm + "] in DispatcherServlet with name '" +getServletName() + "'"); } HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } return null; }

SSM|SpringMVC运行流程 源码分析
文章图片

? 4、如何找到目标处理器的适配器。要拿适配器才去执行目标方法
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { for (HandlerAdapter ha : this.handlerAdapters) { if (logger.isTraceEnabled()) { logger.trace("Testing handler adapter [" + ha + "]"); } // 支持就返回 if (ha.supports(handler)) { return ha; } } throw new ServletException("No adapter for handler [" + handler +"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }

SSM|SpringMVC运行流程 源码分析
文章图片

SSM|SpringMVC运行流程 源码分析
文章图片

SpringMVC九大组件
/** 文件上传解析器 */ private MultipartResolver multipartResolver; /** 区域信息解析器; 和国际化有关 */ private LocaleResolver localeResolver; /** 主题解析器:强大的主题效果更换 */ private ThemeResolver themeResolver; /** Handler映射信息: handlerMappings*/ private List handlerMappings; /** Handler的适配器: handlerAdapters*/ private List handlerAdapters; /** SpringMVC强大的异常解析功能;异常解析器 */ private List handlerExceptionResolvers; /** 视图名称翻译 */ private RequestToViewNameTranslator viewNameTranslator; /** FlashMap + Manager :SpringMVC中运行重定向携带数据的功能 */ private FlashMapManager flashMapManager; /** 视图解析器: */ private List viewResolvers; */ private RequestToViewNameTranslator viewNameTranslator; /** FlashMap + Manager :SpringMVC中运行重定向携带数据的功能 */ private FlashMapManager flashMapManager; /** 视图解析器: */ private List viewResolvers;

    推荐阅读