日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring MVC 中的 forward 和 redirect

發(fā)布時間:2025/7/14 javascript 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring MVC 中的 forward 和 redirect 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?Spring MVC 中,我們在返回邏輯視圖時,框架會通過 viewResolver 來解析得到具體的 View,然后向瀏覽器渲染。假設(shè)邏輯視圖名為 hello,通過配置,我們配置某個 ViewResolver 如下:

Xml代碼:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><description>假如邏輯試圖名為 "hello",因此 viewResolver 將解析成 /WEB-INF/jsp/hello.jsp</description><property name="order" value="10" /><property name="prefix" value="/WEB-INF/jsp/" /><property name="suffix" value=".jsp" /> </bean>

  

實際上,框架還是通過 forward 的方式轉(zhuǎn)發(fā)到了 /WEB-INF/jsp/hello.jsp。如果邏輯視圖名是 /hello,實際還是轉(zhuǎn)發(fā)到了 /WEB-INF/jsp/hello.jsp,即 /WEB-INF/jsp//hello.jsp 等同于 /WEB-INF/jsp/hello.jsp。

現(xiàn)在有個問題,如果 /hello 就是某個 controller 的映射,我想轉(zhuǎn)發(fā)到這個 controller,怎么辦?我們可以通過 forward 前綴來達到轉(zhuǎn)發(fā)到其它資源的目的:

Java代碼:

public String handle() {// return "forward:/hello" => 轉(zhuǎn)發(fā)到能夠匹配 /hello 的 controller 上// return "hello" => 實際上還是轉(zhuǎn)發(fā),只不過是框架會找到該邏輯視圖名對應(yīng)的 View 并渲染// return "/hello" => 同 return "hello"return "forward:/hello"; }

  

?同理,如果我們想重定向到某個資源,我們可以通過 redirect 前綴來達到重定向到其它資源的目的:

java代碼:

public String handle() {// 重定向到 /hello 資源return "redirect:/hello"; }

  

如果想做轉(zhuǎn)發(fā)操作,不需要寫 contextPath;如果想做重定向操作,推薦寫包括 contextPath 在內(nèi)的 url。因此,在使用 Spring MVC 的 redirect 前綴時,里面是有坑的!

仍然假設(shè)應(yīng)用程序的 contextPath 為 /ctx。我們來看看 RedirectView.renderMergedOutputModel 的片段:

java代碼:

protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)throws IOException {// Prepare target URL.StringBuilder targetUrl = new StringBuilder();if (this.contextRelative && getUrl().startsWith("/")) {// Do not apply context path to relative URLs.targetUrl.append(request.getContextPath());}targetUrl.append(getUrl());// ...sendRedirect(request, response, targetUrl.toString(), this.http10Compatible); }protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String targetUrl, boolean http10Compatible)throws IOException {if (http10Compatible) {// Always send status code 302.response.sendRedirect(response.encodeRedirectURL(targetUrl));}else {HttpStatus statusCode = getHttp11StatusCode(request, response, targetUrl);response.setStatus(statusCode.value());response.setHeader("Location", response.encodeRedirectURL(targetUrl));} }

  

sendRedirect 方法沒什么特別的,它就是調(diào)用 HttpServletResponse 的 sendRedirect 方法而已。因此,關(guān)鍵點就是 renderMergedOutputModel 方法對轉(zhuǎn)發(fā)的資源的 url 進行處理了。最終的 url 與 contextRelative 和你要重定向的資源是否以 / 開頭有關(guān)!當且僅當 renderMergedOutputModel 為 true,并且你要重定向的資源是以 / 開頭,spring 會在該資源前添加 contextPath。

response.sendRedirect() 的參數(shù),如果不以 / 開頭,那么容器最終計算出來的資源是相對于做重定向操作的資源的 url;如果以 / 開頭,容器將它視為相對于主機的 url。如此說來,spring 的 RedirectView 怎么著都只能將資源重定向到當前應(yīng)用程序上。將 url 開頭的 / 去掉不是解決之道,因此本機的其它應(yīng)用程序的 contextPath 必定是以 / 開頭,因此我們要想辦法設(shè)置 contextRelative 了。

RedirectView 自身持有 contextRelative 屬性,用于在程序中通過 new 操作符來構(gòu)造一個 RedirectView 并可以設(shè)置 contextRelative。當處理請求的方法返回類型為 String 時,是通過 viewResolver 來解析得到 View 的。UrlBasedViewResolver 就是能夠解析出 RedirectView 的 viewResolver。該 viewResolver 持有 redirectContextRelative 屬性,當它發(fā)現(xiàn)邏輯視圖名以 "redirect:" 開頭時,會將自身持有的 redirectContextRelative 傳入 RedirectView 的構(gòu)造函數(shù)以創(chuàng)建 RedirectView。因此我們通過注冊 UrlBasedViewResolver 時設(shè)置 redirectContextRelative 以達到控制 RedirectView 修改 url 的行為。UrlBasedViewResolver 解析出 View:

java代碼:

protected View createView(String viewName, Locale locale) throws Exception {// If this resolver is not supposed to handle the given view,// return null to pass on to the next resolver in the chain.if (!canHandle(viewName, locale)) {return null;}// Check for special "redirect:" prefix.if (viewName.startsWith(REDIRECT_URL_PREFIX)) {String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());return new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());}// Check for special "forward:" prefix.if (viewName.startsWith(FORWARD_URL_PREFIX)) {String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());return new InternalResourceView(forwardUrl);}// Else fall back to superclass implementation: calling loadView.return super.createView(viewName, locale); }

  

UrlBasedViewResolver 的 redirectContextRelative 的默認值為 true,這意味著,只要重定向的資源以 / 開頭,那么 spring 會幫你添加 contextPath。站在 Spring MVC 的角度上來說,/ 開頭的資源就是相對于當前應(yīng)用程序,這和 forward 一樣了。因此,如果你確定重定向操作是在同一應(yīng)用程序中操作,那就使用 Spring MVC 的默認值吧,這樣就不需要你寫 contextPath 了。注意,這樣做有隱患!當重定向的資源是其它應(yīng)用程序時,除非你了解機制,否則請不要這么做!

轉(zhuǎn)載于:https://www.cnblogs.com/emily1130/p/3713977.html

總結(jié)

以上是生活随笔為你收集整理的Spring MVC 中的 forward 和 redirect的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。