SpringMVC之源碼分析--View(一)

概述

經過上幾章的介紹知道了ViewResolver的做用,即ViewResolver就是把handler返回的邏輯視圖名稱解析爲視圖View對象。進而經過View對象的視圖渲染把最終的結果展示給用戶。web

View視圖渲染的原理,簡單說就是把模型數據填充到視圖模板,最終交由Servlet的response進行渲染展現。瀏覽器

Spring MVC運用模板技術把數據和視圖分開,同時提供支持不少的模板技術,好比:InternalResourceView(JstlView)、FreeMarkerView、Thymeleaf等等。app

本系列文章是基於Spring5.0.5RELEASE。jsp

源碼分析

以InternalResourceView爲例進行分析,該類解析jsp視圖模板,主要涉及類和接口以下:ide

  • View

View接口是Spring MVC提供的視圖渲染接口,定義了render方法對給定的模型數據進行視圖渲染,源碼以下:函數

public interface View {
    ... ...
    /** 把模型數據進行渲染 */
    void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
        throws Exception;
    ... ...
}
  • AbstractView

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);
    }
    ... ...
}
  • InternalResourceView

該類繼承自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,共同窗習、共同進步,謝謝!

相關文章
相關標籤/搜索