controller方法中return語句加關鍵字forward和redirect與否的區別

    如果不加forward和redirect關鍵字,那麼直接在return的字符串上添加springMVC配置文件裏設置好的前綴和後綴,然後轉發到資源。如果加上forward和redirect,那麼就會根據關鍵字不同處理不同,如果是forward,那麼不會拼接配置文件裏設置的前綴和後綴,直接原字符串轉發資源。如果是redirect則再向服務器發送一次新的請求,forward和redirect的區別是前者在服務器端重發,瀏覽器感知不到,地址欄也不會變化。

源碼跟蹤:

不添加forward和redirect關鍵字的情況:

①直接返回success

@RequestMapping("/success")
public String success() {
    return "success";
}

②代碼進入DispatcherServlet類的processDispatchResult()方法中然後調用render()方法準備渲染:

if (mv != null && !mv.wasCleared()) {
    this.render(mv, request, response);

③然後在render()方法中調用resolveViewName()方法,來獲得視圖:

view = this.resolveViewName(mv.getViewName(), mv.getModelInternal(),locale,request);

④在resolveViewName()方法中調用viewResolver.resolveViewName()方法來獲得視圖view,在方法中先從緩存查詢視圖,如果沒有則調用createView()方法創建:

view = this.createView(viewName, locale);

⑤在createView()方法中判斷第①步return的字符串有沒有關鍵字開頭,如果沒有的話則創建一個JstlView類對象並且根據在springmvc配置文件裏設置的前綴和後綴拼接視圖名稱:

return super.createView(viewName, locale);

⑥方法返回後在resolveViewName()方法中把視圖存入緩存:

this.viewAccessCache.put(cacheKey, view);
this.viewCreationCache.put(cacheKey, view);

⑦在DispatcherServlet類的render()方法中調用view.render()方法,渲染視圖:

view.render(mv.getModelInternal(), request, response);

⑧在view.render()方法中調用renderMergedOutputModel()方法,因爲JstlView是InternalResourceView類的子類,所以調用InternalResourceView類的renderMergedOutputModel()方法,調用forward()方法向拼接的視圖名稱地址發送轉發:

rd.forward(request, response);

添加forward關鍵字的情況:

@RequestMapping("/success")
public String success() {
    return "forward:success";
}

①到④步跟不添加關鍵字的情況相同

⑤在createView()方法中判斷第①步return的字符串有沒有關鍵字開頭,如果有forward關鍵字的話則截取forward關鍵字之後的內容然後根據內容創建一個InternalResourceView類對象返回並且放入緩存:

else if (viewName.startsWith("forward:")) {
    forwardUrl = viewName.substring("forward:".length());
return new InternalResourceView(forwardUrl);

⑥方法返回後在resolveViewName()方法中把視圖存入緩存:

this.viewAccessCache.put(cacheKey, view);
this.viewCreationCache.put(cacheKey, view);

⑦在DispatcherServlet類的render()方法中調用view.render()方法,渲染視圖:

view.render(mv.getModelInternal(), request, response);

⑧最後跳轉到InternalResourceView類的renderMergedOutputModel()方法中,調用forward()方法向上一步獲取的地址發送轉發:

rd.forward(request, response);

添加redirect關鍵字的情況:

@RequestMapping("/success")
public String success() {
    return "redirect:success";
}

①到④步跟不添加關鍵字的情況相同

⑤在createView()方法中判斷第①步return的字符串有沒有關鍵字開頭,如果有redirect關鍵字的話則截取redirect關鍵字之後的內容創建一個RedirectView類對象並返回:

if (viewName.startsWith("redirect:")) {
forwardUrl = viewName.substring("redirect:".length());
RedirectView view = new RedirectView(forwardUrl, this.isRedirectContextRelative(), 

⑥方法返回後在resolveViewName()方法中把視圖存入緩存:

this.viewAccessCache.put(cacheKey, view);
this.viewCreationCache.put(cacheKey, view);

⑦在DispatcherServlet類的render()方法中調用view.render()方法,渲染視圖:

view.render(mv.getModelInternal(), request, response);

⑧最後跳轉到RedirectView類的renderMergedOutputModel()方法,並調用sendRedirect()方法來重定向:

this.sendRedirect(request, response, targetUrl, this.http10Compatible);

⑨在sendRedirect()方法中重定向:

response.sendRedirect(encodedURL);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章