天天看點

springMVC源碼分析--RequestToViewNameTranslator請求到視圖名稱的轉換

RequestToViewNameTranslator可以在處理器傳回的View為空時使用它根據Request擷取viewName。RequestToViewNameTranslator提供的實作類隻有一個DefaultRequestToViewNameTranslator。

接口RequestToViewNameTranslator中定義的如下:提供了getViewName抽象方法,其實就是根據request請求擷取來組裝視圖名稱。

public interface RequestToViewNameTranslator {

  /**
   * Translate the given {@link HttpServletRequest} into a view name.
   * @param request the incoming {@link HttpServletRequest} providing
   * the context from which a view name is to be resolved
   * @return the view name (or {@code null} if no default found)
   * @throws Exception if view name translation fails
   */
  String getViewName(HttpServletRequest request) throws Exception;

}      

其實作類DefaultRequestToViewNameTranslator中的實作如下:其實其簡單實作就是将請求名稱作為視圖名稱傳回,邏輯還是比較簡單的。

@Override
  public String getViewName(HttpServletRequest request) {
    String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
    return (this.prefix + transformPath(lookupPath) + this.suffix);
  }      

接下來我們看看RequestToViewNameTranslator在springMVC中的具體運作流程:

首先在DispatcherServlet的doDispatch函數中會設定預設的視圖名

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    ......
    //設定預設的視圖名稱
    applyDefaultViewName(processedRequest, mv);
    ......
  }      

在applyDefaultViewName中會判斷ModelAndView的hasView為空時,就設定viewName

private void applyDefaultViewName(HttpServletRequest request, ModelAndView mv) throws Exception {
    if (mv != null && !mv.hasView()) {
      mv.setViewName(getDefaultViewName(request));
    }
  }      

getDefaultViewName的實作邏輯還是在ViewNameTranslator中。

protected String getDefaultViewName(HttpServletRequest request) throws Exception {
    return this.viewNameTranslator.getViewName(request);
  }      

在DefaultViewNameTranslator中實作的getViewName的邏輯如下,其實就是将請求路徑作為ViewName

@Override
  public String getViewName(HttpServletRequest request) {
    String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
    return (this.prefix + transformPath(lookupPath) + this.suffix);
  }      

實作類DefaultViewNameTranslator的完整源碼如下:

public class DefaultRequestToViewNameTranslator implements RequestToViewNameTranslator {

  private static final String SLASH = "/";


  private String prefix = "";

  private String suffix = "";

  private String separator = SLASH;

  private boolean stripLeadingSlash = true;

  private boolean stripTrailingSlash = true;

  private boolean stripExtension = true;

  private UrlPathHelper urlPathHelper = new UrlPathHelper();


  
  public void setPrefix(String prefix) {
    this.prefix = (prefix != null ? prefix : "");
  }

  public void setSuffix(String suffix) {
    this.suffix = (suffix != null ? suffix : "");
  }

  public void setSeparator(String separator) {
    this.separator = separator;
  }

  public void setStripLeadingSlash(boolean stripLeadingSlash) {
    this.stripLeadingSlash = stripLeadingSlash;
  }

  public void setStripTrailingSlash(boolean stripTrailingSlash) {
    this.stripTrailingSlash = stripTrailingSlash;
  }

  public void setStripExtension(boolean stripExtension) {
    this.stripExtension = stripExtension;
  }

  
  public void setAlwaysUseFullPath(boolean alwaysUseFullPath) {
    this.urlPathHelper.setAlwaysUseFullPath(alwaysUseFullPath);
  }

  
  public void setUrlDecode(boolean urlDecode) {
    this.urlPathHelper.setUrlDecode(urlDecode);
  }

  public void setRemoveSemicolonContent(boolean removeSemicolonContent) {
    this.urlPathHelper.setRemoveSemicolonContent(removeSemicolonContent);
  }

  public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
    Assert.notNull(urlPathHelper, "UrlPathHelper must not be null");
    this.urlPathHelper = urlPathHelper;
  }

  //根據請求擷取視圖名稱
  @Override
  public String getViewName(HttpServletRequest request) {
    String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
    return (this.prefix + transformPath(lookupPath) + this.suffix);
  }

  
  protected String transformPath(String lookupPath) {
    String path = lookupPath;
    if (this.stripLeadingSlash && path.startsWith(SLASH)) {
      path = path.substring(1);
    }
    if (this.stripTrailingSlash && path.endsWith(SLASH)) {
      path = path.substring(0, path.length() - 1);
    }
    if (this.stripExtension) {
      path = StringUtils.stripFilenameExtension(path);
    }
    if (!SLASH.equals(this.separator)) {
      path = StringUtils.replace(path, SLASH, this.separator);
    }
    return path;
  }

}