如果不加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);