springMVC源码分析
本篇將涉及,通過本篇可以對整個springmvc模塊有一個清晰的視角,在日常開發中可以快速定位問題和源碼
springMVC應用啟動初始化過程分析
初始化過程應該分為三步:
- 第一步,創建兩個spring的ApplicationContext,配置DispatcherServlet、filter、ContextLoaderListener到servlet容器中
- 第二步,servlet容器啟動后,調用ContextLoaderListener#contextInitialized初始化必要的bean(如DAO、service相關的bean)
- 第三步,調用DispatcherServlet#init方法進一步初始化必要的bean(如HandlerMappings、HandlerMappingAdapter等)
第一步
主要完成以下工作:第二步
主要完成以下工作:第三步
在這一步中,分為兩個階段:
SourceFilteringListener的職責
先來看一下其類關系圖
SourceFilteringListener作為EventListener的實現類,在servlet的ApplicationContext初始化后,將收到事件回調完成剩余的初始化工作 protected void initStrategies(ApplicationContext context) {initMultipartResolver(context);initLocaleResolver(context);initThemeResolver(context);initHandlerMappings(context);initHandlerAdapters(context);initHandlerExceptionResolvers(context);initRequestToViewNameTranslator(context);initViewResolvers(context);initFlashMapManager(context); } 復制代碼在這些初始化方法中,注冊到spring容器中的bean由注解@EnableWebMVC導入。 導入工作委托給了DelegatingWebMvcConfiguration類
以上就是springMVC的初始化過程的整體脈絡
springMVC處理請求過程分析
整體流程
整個過程相對比較復雜,整個邏輯在DispatcherServlet#doDispatcher方法中實現,該方法內部將具體工作委托給了RequestMappingHandlerMapping、HandlerExcutionChain、RequestMappingHandlerAdapter、ViewResolver、View等幾個核心類來完成任務。 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);// Determine handler for the current request.// 獲取HandlerExcutionChainmappedHandler = getHandler(processedRequest);if (mappedHandler == null || mappedHandler.getHandler() == null) {noHandlerFound(processedRequest, response);return;}// 獲取HandlerAdapter// Determine handler adapter for the current request.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;}// 真正調用HandlerMethod(即Controller方法),內部涉及了參數解析(處理@RequestParams、@PathVariables注解原理)、參數類型轉換、HandlerMethod執行結果處理(@ResponseBody注解原理)這幾個步驟。后面內容我們詳細剖析這個函數的內部機制// Actually invoke the handler.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) {triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Throwable err) {triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException("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);}}} } 復制代碼根據請求尋找對應的HandlerMethod
具體尋找過程的代碼細節如下:HandlerMethod執行細節
參數解析以及類型轉換
主要是通過HandlerMethodArgumentResolverComposite這個特殊的HandlerMethodArgumentResolver聚合了多個HandlerMethodArgumentResolver來解析參數、其內部將調用RequestParamMethodArgumentResolver、PathVariableMapMethodArgumentResolver等來處理參數解析邏輯
返回結果處理
主要是通過HandlerMethodReturnValueHandlerComposite這個特殊的HandlerMethodReturnValueHandler聚合了多個HandlerMethodReturnValueHandler來處理返回結果,其內部將調用RequestResponseBodyMethodProcessor處理@ResponseBody、@RestController標記的方法和類來完成RESTful接口的結果返回
總結
以上就是整個springmvc的工作流程,包括了初始化、請求處理兩個步驟。在請求處理的過程中又涉及到了參數解析、參數類型轉換、返回結果處理這些流程。由于整個代碼比較繁多,這里就不列舉所有的流程(視圖渲染、異常處理這些細節)通過本篇的主體流程圖可以快速定位到具體的代碼。后續有需要查看更多細節可參考本篇快速定位
轉載于:https://juejin.im/post/5c2c0a39e51d4563d9209c33
總結
以上是生活随笔為你收集整理的springMVC源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sqlyog软件的使用
- 下一篇: 大数据正在改变汽车行业的5种方式