經過上幾章的介紹知道了ViewResolver的做用,即ViewResolver就是把handler返回的邏輯視圖名稱解析爲視圖View對象。進而經過View對象的視圖渲染把最終的結果展示給用戶。web
View視圖渲染的原理,簡單說就是把模型數據填充到視圖模板,最終交由Servlet的response進行渲染展現。瀏覽器
Spring MVC運用模板技術把數據和視圖分開,同時提供支持不少的模板技術,好比:InternalResourceView(JstlView)、FreeMarkerView、Thymeleaf等等。app
本系列文章是基於Spring5.0.5RELEASE。jsp
以InternalResourceView爲例進行分析,該類解析jsp視圖模板,主要涉及類和接口以下:ide
View接口是Spring MVC提供的視圖渲染接口,定義了render方法對給定的模型數據進行視圖渲染,源碼以下:函數
public interface View { ... ... /** 把模型數據進行渲染 */ void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception; ... ... }
AbstractView是實現View接口的抽象類,實現了render方法,源碼以下:源碼分析
public abstract class AbstractView extends WebApplicationObjectSupport implements View, BeanNameAware { ... ... @Override public void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { if (logger.isTraceEnabled()) { logger.trace("Rendering view with name '" + this.beanName + "' with model " + model + " and static attributes " + this.staticAttributes); } // 建立整合後須要返回給瀏覽器的Model Map<String, Object> mergedModel = createMergedOutputModel(model, request, response); // 設置response 報文頭 prepareResponse(request, response); // 渲染數據,經過模板方法由子類實現,如InternalResourceView renderMergedOutputModel(mergedModel, getRequestToExpose(request), response); } ... ... }
該類繼承自AbstractView,並實現renderMergedOutputModel方法,源碼以下:學習
@Override protected void renderMergedOutputModel( Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // 將model中的數據設置到request exposeModelAsRequestAttributes(model, request); // 本類中的此函數是空函數,留給子類好比JstlView去實現自定義邏輯 exposeHelpers(request); // 跳轉目的頁面路徑 String dispatcherPath = prepareForRendering(request, response); // 獲取跳轉控制器RequestDispatcher RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath); if (rd == null) { throw new ServletException("Could not get RequestDispatcher for [" + getUrl() + "]: Check that the corresponding file exists within your web application archive!"); } // 直接返回用戶資源 if (useInclude(request, response)) { response.setContentType(getContentType()); if (logger.isDebugEnabled()) { logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'"); } rd.include(request, response); } // 攜帶request和response跳轉到另外一個控制器方法 else { // Note: The forwarded resource is supposed to determine the content type itself. if (logger.isDebugEnabled()) { logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'"); } rd.forward(request, response); } }
至此,View渲染視圖的大體流程結束,也就是Spring MVC基本完成了整個流程,剩下的渲染工做交由Servlet去處理。this
本章就View視圖渲染進行了簡單的分析,Spring 提供了衆多的View實現,有興趣的童鞋能夠繼續瞭解。spa
最後建立了qq羣方便你們交流,可掃描加入,同時也可加我qq:276420284,共同窗習、共同進步,謝謝!