Spring原始碼追蹤4——SpringMVC View解析
這次的議題是返回json和返回普通view經過的路線差異。
---------------------------------------------------------------------------------
org.springframework.web.servlet.DispatcherServlet#doDispatch
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. mappedHandler = getHandler(processedRequest); if (mappedHandler == null|| mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // 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; } // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(request, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } 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); } } } }
1 view的設定
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandleMethod
private ModelAndView invokeHandleMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, requestMappingMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this.asyncRequestTimeout); final WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.setTaskExecutor(this.taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); asyncManager.registerCallableInterceptors(this.callableInterceptors); asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); if (asyncManager.hasConcurrentResult()) { Object result = asyncManager.getConcurrentResult(); mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0]; asyncManager.clearConcurrentResult(); if (logger.isDebugEnabled()) { logger.debug("Found concurrent result value [" + result + "]"); } requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result); } requestMappingMethod.invokeAndHandle(webRequest, mavContainer); // 請求並設定mavContainer if (asyncManager.isConcurrentHandlingStarted()) { return null; } return getModelAndView(mavContainer, modelFactory, webRequest); }
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite#getReturnValueHandler
private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) { for (HandlerMethodReturnValueHandler returnValueHandler : returnValueHandlers) { if (logger.isTraceEnabled()) { logger.trace("Testing if return value handler [" + returnValueHandler + "] supports [" + returnType.getGenericParameterType() + "]"); } if (returnValueHandler.supportsReturnType(returnType)) { // 遍歷獲取合適的returnValueHandler return returnValueHandler; } } return null; }
1.1 根據viewName來解析的Handler
org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler#supportsReturnType
public boolean supportsReturnType(MethodParameter returnType) { Class<?> paramType = returnType.getParameterType(); return (void.class.equals(paramType) || String.class.equals(paramType)); }
org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler#handleReturnValue
public void handleReturnValue( Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { if (returnValue == null) { return; } else if (returnValue instanceof String) { String viewName = (String) returnValue; mavContainer.setViewName(viewName); if (isRedirectViewName(viewName)) { mavContainer.setRedirectModelScenario(true); } } else { // should not happen throw new UnsupportedOperationException("Unexpected return type: " + returnType.getParameterType().getName() + " in method: " + returnType.getMethod()); } }
1.2 支援ResponseBody的Handler
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor#supportsReturnType
public boolean supportsReturnType(MethodParameter returnType) { return ((AnnotationUtils.findAnnotation(returnType.getContainingClass(), ResponseBody.class) != null) || (returnType.getMethodAnnotation(ResponseBody.class) != null)); }
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor#handleReturnValue
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException { mavContainer.setRequestHandled(true); if (returnValue != null) { writeWithMessageConverters(returnValue, returnType, webRequest); } }
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor#writeWithMessageConverters(T, org.springframework.core.MethodParameter, org.springframework.http.server.ServletServerHttpRequest, org.springframework.http.server.ServletServerHttpResponse)
protected <T> void writeWithMessageConverters(T returnValue, MethodParameter returnType, ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) throws IOException, HttpMediaTypeNotAcceptableException { Class<?> returnValueClass = returnValue.getClass(); HttpServletRequest servletRequest = inputMessage.getServletRequest(); List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(servletRequest); List<MediaType> producibleMediaTypes = getProducibleMediaTypes(servletRequest, returnValueClass); Set<MediaType> compatibleMediaTypes = new LinkedHashSet<MediaType>(); for (MediaType requestedType : requestedMediaTypes) { for (MediaType producibleType : producibleMediaTypes) { if (requestedType.isCompatibleWith(producibleType)) { compatibleMediaTypes.add(getMostSpecificMediaType(requestedType, producibleType)); } } } if (compatibleMediaTypes.isEmpty()) { throw new HttpMediaTypeNotAcceptableException(producibleMediaTypes); } List<MediaType> mediaTypes = new ArrayList<MediaType>(compatibleMediaTypes); MediaType.sortBySpecificityAndQuality(mediaTypes); MediaType selectedMediaType = null; for (MediaType mediaType : mediaTypes) { if (mediaType.isConcrete()) { selectedMediaType = mediaType; break; } else if (mediaType.equals(MediaType.ALL) || mediaType.equals(MEDIA_TYPE_APPLICATION)) { selectedMediaType = MediaType.APPLICATION_OCTET_STREAM; break; } } if (selectedMediaType != null) { selectedMediaType = selectedMediaType.removeQualityValue(); for (HttpMessageConverter<?> messageConverter : this.messageConverters) { // 遍歷獲取合適的messageConverter(mediaType) if (messageConverter.canWrite(returnValueClass, selectedMediaType)) { returnValue = this.adviceChain.invoke(returnValue, returnType, selectedMediaType, (Class<HttpMessageConverter<?>>) messageConverter.getClass(), inputMessage, outputMessage); ((HttpMessageConverter<T>) messageConverter).write(returnValue, selectedMediaType, outputMessage); if (logger.isDebugEnabled()) { logger.debug("Written [" + returnValue + "] as \"" + selectedMediaType + "\" using [" + messageConverter + "]"); } return; } } } throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes); }
2.設定了viewName的view解析
org.springframework.web.servlet.DispatcherServlet#processDispatchResult
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, 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); } } // Did the handler return a view to render? if (mv != null && !mv.wasCleared()) { // 如果沒有設定view則不會進入viewResolver,返回json物件就不進入viewResolver render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else { if (logger.isDebugEnabled()) { logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() + "': assuming HandlerAdapter completed request handling"); } } if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Concurrent handling started during a forward return; } if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, null); } }
org.springframework.web.servlet.DispatcherServlet#resolveViewName
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception { for (ViewResolver viewResolver : this.viewResolvers) { // 遍歷獲取合適的viewResolver View view = viewResolver.resolveViewName(viewName, locale); if (view != null) { return view; } } return null; }
相關推薦
Spring原始碼追蹤4——SpringMVC View解析
這次的議題是返回json和返回普通view經過的路線差異。 --------------------------------------------------------------------------------- org.springframework.web.servlet.Dispatche
Spring原始碼追蹤2——xml解析入口
解析xml節點入口 org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root) protected void doRegisterBe
Spring原始碼分析4 — spring bean建立和初始化
1 介紹 建立並初始化spring容器中,refresh()方法中解析xml配置檔案,註冊容器後處理器,bean後處理器,初始化MessageSource,ApplicationEventMulticaster廣播器,註冊完ApplicationListene
Spring原始碼閱讀4.2-Aspecjt AOP之代理物件的建立
繼續上一篇的話題,在《Spring原始碼閱讀4.1-Aspecjt AOP之獲取Adivsor》,我們說獲取了所有的AspectJ以及其Advisor,其中每個Advisor都和其Aspectj類的表示式一起快取到了陣列中,以便後續直接使用。在這裡要補充一下Instan
Spring原始碼追蹤3——AOP機制
研究程式碼: spring配置檔案 <cache:annotation-driven /> Java程式碼 @Cacheable(value = "test", key = "#city") public Map load(String city) {} 【cach
spring原始碼(4)Register the bean definitions(3)
在閱讀本文之前,請務必先閱讀:spring原始碼(5)父子beans標籤之間的屬性關係 本節介紹bean標籤的其他屬性的解析 public AbstractBeanDefinition parseBeanDefinitionAttribute
Spring原始碼之bean的基本解析
先看這樣一段兒程式碼: spring bean xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchem
4、Spring原始碼分析4之初始化Bean
1、記錄建立bean的ObjectFactory,目的是為了解決迴圈依賴 if (instanceWrapper == null)
《spring原始碼解讀》 - IoC 之解析 import 標籤
![spring-framework.jpg](https://img2020.cnblogs.com/other/2024393/202009/2024393-20200902154305425-1091612735.jpg) 在上一文中我們分析了註冊 `BeanDefinition` 的過程,在其中我們
Spring原始碼分析之AOP從解析到呼叫
正文: 在上一篇,我們對IOC核心部分流程已經分析完畢,相信小夥伴們有所收穫,從這一篇開始,我們將會踏上新的旅程,即Spring的另一核心:AOP! 首先,為了讓大家能更有效的理解AOP,先帶大家過一下AOP中的術語: - **切面(Aspect)**:指關注點模組化,這個關注點可能會橫切多個物件。事務
Spring原始碼解析(四)——元件註冊4
/** * 給容器中註冊元件; * 1)、包掃描+元件標註註解(@Controller/@Service/@Repository/@Component)[自己寫的類] * 2)、@Bean[匯入的第三方包裡面的元件] * 3)、@Import[快速給容器中匯入一個
Spring原始碼解析(四):SpringMVC原始碼解析
SpringMVC是Spring一個非常重要的模組,從大體上看,在使用SpringMVC的時候,需要在web.xml中配置DispatcherServlet,這個DispatcherServlet可以看成是一個前端控制器的實現,web請求會通過它分發給各個對應的Control
Spring原始碼解析之SpringMVC
1、說在前面的話 ①、在說springmvc之前先說一下與之相關的一些類與介面:ContextLoaderListener與ServletContextListener,ContextLoaderListener實現了ServletContextListener介面。 Context
Spring原始碼解析-4、IOC容器初始化
IOC容器初始化的幾個步驟 IOC容器的初始化由以下三個步驟構成: 1、BeanDefinition的Resource定位 由ResourceLoader通過統一的Resource介面來完成,Resource對不同形式的BeanDefinition有統一的介面。 比如檔案系統中的Bean
(Spring原始碼解析)一步一步分析,springMVC專案啟動過程(一)
springMVC專案啟動過程,分析原始碼。1、環境搭建,這步我就省略細節,只把我的大概環境說下:windows 7 、jdk 8、maven-3.3.9、tomcat 8.5.11、IDEA 2017.1 x64版 具體環境安裝,我就略過,可自行google、baidu安
Spring原始碼解析(4):IOC過程下
上文說到populateBean方法中,對被@Autowired註解的屬性方法進行注入。在這之後,BeanFactory執行applyPropertyValues方法,這個方法中,一個是把之前解析出來的屬性值設定到bean中去;一個是繼續解析出BeanDefinition中定
【Spring原始碼解析】—— 結合SpringMVC過程理解IOC容器初始化之註解部分探究
前面的文章寫了xml中直接配置bean進行IOC的過程解析,接下來會針對註解進行IOC容器初始化的過程解析 因為會與之前的內容存在部分重疊,因此會針對相同的部分簡略帶過,針對不同的部分做重點說明: 一、Xml的配置和程式碼中的註解配置: applicationContext.xml配置新
Spring原始碼解析(十六)——AOP原理——獲取攔截器鏈——MethodInterceptor
* 3)、目標方法執行 ; * 容器中儲存了元件的代理物件(cglib增強後的物件),這個物件裡面儲存了詳細
Spring原始碼解析(十五)——AOP原理——建立aop代理
* AnnotationAwareAspectJAutoProxyCreator【InstantiationAwareBeanPostProcessor】 的作用: * 1)、每一個bean建立之前,呼叫postProce
Spring原始碼解析(十四)——AOP原理——AnnotationAwareAspectJAutoProxyCreator執行時機
* AnnotationAwareAspectJAutoProxyCreator => InstantiationAwareBean