SpringMVC源码分析
2020-12-10 15:04
176 查看
目录三,getHandler()方法分析 四,getHandlerAdapter()方法——适配器获取分析 五,SpringMVC九大组件初始化 5.2 九大组件初始化细节:5.2.1 initHandlerMappings(context) ***注意 多文件上传的组件(MultipartResolver)必须按照id注册对象: 六,Handler方法细节刨析: 七,processDispatchResult方法 image-20201208221146139
- 一,DispatcherServlet继承结构
- 二、SpringMvc请求处理的大致流程2.1 Handler方法执行的时机
- 2.2 页面渲染时机(打断点并观察调用栈)
- 3.3 doDispatch()方法核心步骤 (Springmvc处理请求的大致流程):
一,DispatcherServlet继承结构
二、SpringMvc请求处理的大致流程
2.1 Handler方法执行的时机
打断点:
观察调用栈:
doDispathch⽅法中的1064⾏代码完成handler⽅法的调⽤
2.2 页面渲染时机(打断点并观察调用栈)
3.3 doDispatch()方法核心步骤 (Springmvc处理请求的大致流程):
- 调用
getHandler()
获取到能够处理当前请求的执行链HandlerExecutionChain
(Handler + 拦截器) - 调用
getHandlerAdapter()
获取能够执行Handler的适配器 - 适配器调用Handler执行
ha.handle()
,总会返回一个ModelAndView对象 - 调用
processDispatchResult()
方法完成视图跳转
//org.springframework.web.servlet.DispatcherServlet protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; //执行器链,包含了handler和一些拦截器 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. 取得处理当前请求的Controller,这里也称为Handler,即处理器。这里并不是直接返回controller, 而是返回HandlerExecutionChain 请求处理链对象 该对象封装了Handler和Inteceptor */ mappedHandler = getHandler( 1044 processedRequest); if (mappedHandler == null) { // 如果handler为空, 则返回404 noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. // 3. 获取处理请求的处理器适配器 HandlerAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. // 处理last-modeified 请求头 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; } // Actually invoke the handler. // 4 实际处理器处理请求,返回结果视图对象 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) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } //跳转视图页面,渲染视图 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);} catch (Exception ex) { //最终会调用HandlerInterceptor的afterCompletion方法 //========拦截器的第三个拦截时机————视图页面渲染完成之后拦截 triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { //最终会调用HandlerInterceptor的afterCompletion方法 //========拦截器的第三个拦截时机————视图页面渲染完成之后拦截 triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", 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); } } } }
三,getHandler()方法分析
@Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { //handlerMappings是一个 ArrayList ———— List<HandlerMapping> handlerMappings //而HandlerMapping 则存储了url和handler的映射关系 if (this.handlerMappings != null) { /** * 遍历 handlerMappings : * 1. BeanNameUrlHandlerMapping ,早期的一种使用方式 * 2. RequestMappingHandlerMapping,我们的请求所使用的 */ for (HandlerMapping mapping : this.handlerMappings) { HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }
HandlerExecutionChain 包含了 DemoController.handle01 以及 0个 interceptors
Q:HandlerMapping里面的映射关系是在何时进行初始化的?
A:在容器启动时时,IOC容器在扫描@Controller对象时会扫描@RequestMapping注解,然后就可 25ec 以建立url和handler方法的映射关系
四,getHandlerAdapter()方法——适配器获取分析
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { //List<HandlerAdapter> handlerAdapters if (this.handlerAdapters != null) { /* 遍历 handlerAdapters: 遍历各个HandlerAdapter,看哪个Adapter⽀持处理当前Handler: handlerAdapters是一个List<HandlerAdapter>,HandlerAdapter是一个接口,里面有几个实现类: 1. HttpRequestHandlerAdapter ——实现接口的方式 2. SimpleControllerHandlerAdapter ——实现Controller接口的方式 3. RequestMappingHandlerAdapter ——是不是HandlerMethod(RequestMappingHandlerMapping封装的)的实例 */ 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"); }
Q:handlerAdapters 中三个 实现类是如何初始化的?
A:这些组件简单的说也是容器启动时初始化的。
五,SpringMVC九大组件初始化
5.1 九大组件
//org.springframework.web.servlet.DispatcherServlet //多部件解析器,文件上传之类的 @Nullable private MultipartResolver multipartResolver; //区域化 国际化解析器 @Nullable private LocaleResolver localeResolver; //主题解析器 @Nullable private ThemeResolver themeResolver; //处理器映射器组件 @Nullable private List<HandlerMapping> handlerMappings; //处理器适配器组件 @Nullable private List<HandlerAdapter> handlerAdapters; //异常解析器 @Nullable private List<HandlerExceptionResolver> handlerExceptionResolvers; //默认视图名转换器组件 @Nullable private RequestToViewNameTranslator viewNameTranslator; //flash属性管理组件 @Nullable private FlashMapManager flashMapManager; //视图解析器 @Nullable private List<ViewResolver> viewResolvers;
上述九大组件都是定义了接口,接口其实是定义了规范。
5.2 九大组件初始化细节:
//org.springframework.web.servlet.DispatcherServlet //主要完成组件的初始化 @Override protected void onRefresh(ApplicationContext context) { //初始化策略 initStrategies(context); }
protected void initStrategies(ApplicationContext context) { // 多文件上传的组件 initMultipartResolver(context); // 初始化本地语语言环境 initLocaleResolver(context); // 初始化模板处理器 initThemeResolver(context); // 初始化HandlerMapping initHandlerMappings(context); // 初始化参数适配器 initHandlerAdapters(context); // 初始化异常拦截器 initHandlerExceptionResolvers(context); // 初始化视图预处理器 initRequestToViewNameTranslator(context); // 初始化视图转换器 initViewResolvers(context); // 初始化FlashMap 管理器 initFlashMapManager(context); }
onRefresh方法何时被调用?
在此方法中打一个断点,然后Debug模式启动,然后观察调用栈。
可以看到,最初是由
refresh方法调用的——
finishRefresh(),由
finishRefresh()发布事件,然后触发事件监听,最终到了
onRefresh方法。
重点来看:
5.2.1 initHandlerMappings(context)
默认的配置:
initHandlerAdapters同理
***注意 多文件上传的组件(MultipartResolver)必须按照id注册对象:
六,Handler方法细节刨析:
//org.springframework.web.servlet.DispatcherServlet#doDispatch // 4 实际处理器处理请求,返回结果视图对象 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
七,processDispatchResult方法
//跳转视图页面,渲染视图 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
render方法完成渲染
相关文章推荐
- springMVC源码分析--页面跳转RedirectView(三)
- SpringMVC加载WebApplicationContext源码分析
- springMVC系列之源码分析1
- SpringMVC-前端控制器源码分析
- springMVC源码分析
- SpringMVC拦截器详解[附带源码分析]
- Spring源码分析: SpringMVC启动流程与DispatcherServlet请求处理流程
- springMVC方法参数值注入简要源码分析
- springMVC源码分析--AbstractHandlerMapping(二)
- springMVC源码分析--RequestToViewNameTranslator请求到视图名称的转换
- springMVC源码分析--HandlerMapping(一)
- springMVC源码分析--SimpleUrlHandlerMapping(四)
- springMVC源码分析--HandlerMethodReturnValueHandlerComposite返回值解析器集合(二)
- SpringMVC工作原理(源码分析)
- “过时”的SpringMVC我们到底在用什么?深入分析DispatchServlet源码
- springMVC源码分析--HttpRequestHandlerAdapter(四)
- SpringMVC类型转换、数据绑定详解[附带源码分析]
- SpringMVC关于json、xml自动转换的原理研究[附带源码分析]
- SpringMVC核心分发器DispatcherServlet分析[附带源码分析]
- springMVC源码分析--RequestMappingHandlerAdapter(五)