本文共 12433 字,大约阅读时间需要 41 分钟。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | String getContentType(); /** * Render the view given the specified model. * <p>The first step will be preparing the request: In the JSP case, * this would mean setting model objects as request attributes. * The second step will be the actual rendering of the view, * for example including the JSP via a RequestDispatcher. * @param model Map with name Strings as keys and corresponding model * objects as values (Map can also be {@code null} in case of empty model) * @param request current HTTP request * @param response HTTP response we are building * @throws Exception if rendering failed */ //上面说的很清楚,对于jsp来说,第一步就是将model作为request的attributes;第二步才开始渲染view void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception; |
1 | View resolveViewName(String viewName, Locale locale) throws Exception; |
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 | try { // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); } finally { 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); } |
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 | 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()) { 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 ); } } |
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 | protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine locale for request and apply it to the response. Locale locale = this .localeResolver.resolveLocale(request); response.setLocale(locale); View view; if (mv.isReference()) { // We need to resolve the view name. view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); if (view == null ) { throw new ServletException( "Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + getServletName() + "'" ); } } else { // No need to lookup: the ModelAndView object contains the actual View object. 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() + "'" ); } } // Delegate to the View object for rendering. if (logger.isDebugEnabled()) { logger.debug( "Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'" ); } try { view.render(mv.getModelInternal(), request, response); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug( "Error rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'" , ex); } throw ex; } } |
1 2 3 4 5 6 7 8 9 10 11 | protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception { for (ViewResolver viewResolver : this .viewResolvers) { View view = viewResolver.resolveViewName(viewName, locale); if (view != null ) { return view; } } return null ; } |
1 2 3 4 5 6 7 8 9 10 11 12 | protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); //我们关注的重点 initViewResolvers(context); initFlashMapManager(context); } |
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 | private void initViewResolvers(ApplicationContext context) { this .viewResolvers = null ; if ( this .detectAllViewResolvers) { // Find all ViewResolvers in the ApplicationContext, including ancestor contexts. Map<String, ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver. class , true , false ); if (!matchingBeans.isEmpty()) { this .viewResolvers = new ArrayList<ViewResolver>(matchingBeans.values()); // We keep ViewResolvers in sorted order. OrderComparator.sort( this .viewResolvers); } } else { try { ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver. class ); this .viewResolvers = Collections.singletonList(vr); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we'll add a default ViewResolver later. } } // Ensure we have at least one ViewResolver, by registering // a default ViewResolver if no other resolvers are found. if ( this .viewResolvers == null ) { this .viewResolvers = getDefaultStrategies(context, ViewResolver. class ); if (logger.isDebugEnabled()) { logger.debug( "No ViewResolvers found in servlet '" + getServletName() + "': using default" ); } } } |
1 2 | /** Detect all ViewResolvers or just expect "viewResolver" bean? */ private boolean detectAllViewResolvers = true ; |
1 | org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <bean class = "org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer" > <property name= "templateLoaderPath" value= "/WEB-INF/views" /> <property name= "defaultEncoding" value= "utf-8" /> <property name= "freemarkerSettings" > <props> <prop key= "locale" >zh_CN</prop> </props> </property> </bean> <bean class = "org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver" > <property name= "suffix" value= ".html" /> <property name= "contentType" value= "text/html;charset=utf-8" /> <property name= "requestContextAttribute" value= "request" /> <property name= "exposeRequestAttributes" value= "true" /> <property name= "exposeSessionAttributes" value= "true" /> </bean> |
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 | /** Default maximum number of entries for the view cache: 1024 */ public static final int DEFAULT_CACHE_LIMIT = 1024 ; /** The maximum number of entries in the cache */ private volatile int cacheLimit = DEFAULT_CACHE_LIMIT; /** Fast access cache for Views, returning already cached instances without a global lock */ private final Map<Object, View> viewAccessCache = new ConcurrentHashMap<Object, View>(DEFAULT_CACHE_LIMIT); /** Map from view key to View instance, synchronized for View creation */ @SuppressWarnings ( "serial" ) private final Map<Object, View> viewCreationCache = new LinkedHashMap<Object, View>(DEFAULT_CACHE_LIMIT, 0 .75f, true ) { @Override protected boolean removeEldestEntry(Map.Entry<Object, View> eldest) { if (size() > getCacheLimit()) { viewAccessCache.remove(eldest.getKey()); return true ; } else { return false ; } } }; |
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 | public View resolveViewName(String viewName, Locale locale) throws Exception { //这里进行了是否进行缓存的判断,即cacheLimit是否大于0 if (!isCache()) { //不进行缓存,始终每次都创建 return createView(viewName, locale); } else { //viewAccessCache viewCreationCache两者的key Object cacheKey = getCacheKey(viewName, locale); View view = this .viewAccessCache.get(cacheKey); if (view == null ) { synchronized ( this .viewCreationCache) { view = this .viewCreationCache.get(cacheKey); if (view == null ) { // Ask the subclass to create the View object. view = createView(viewName, locale); if (view == null && this .cacheUnresolved) { view = UNRESOLVED_VIEW; } if (view != null ) { this .viewAccessCache.put(cacheKey, view); this .viewCreationCache.put(cacheKey, view); if (logger.isTraceEnabled()) { logger.trace( "Cached view [" + cacheKey + "]" ); } } } } } return (view != UNRESOLVED_VIEW ? view : null ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | private final Map<Object, View> viewAccessCache = new ConcurrentHashMap<Object, View>(DEFAULT_CACHE_LIMIT); private final Map<Object, View> viewCreationCache = new LinkedHashMap<Object, View>(DEFAULT_CACHE_LIMIT, 0 .75f, true ) { @Override protected boolean removeEldestEntry(Map.Entry<Object, View> eldest) { if (size() > getCacheLimit()) { viewAccessCache.remove(eldest.getKey()); return true ; } else { return false ; } } }; |
转载地址:http://txkzl.baihongyu.com/