天來聊一個 JavaWeb 中簡單的話題,但是感覺卻比較稀罕,因為這個技能點,有的小伙伴們可能沒聽過!
說到 Web 請求參數傳遞,大家能想到哪些參數傳遞方式?
參數可以放在地址欄中,不過地址欄參數的長度有限制,并且在有的場景下我們可能不希望參數暴漏在地址欄中。參數可以放在請求體中,這個沒啥好說的。
小伙伴們試想這樣一個場景:
在一個電商項目中,有一個提交訂單的請求,這個請求是一個 POST 請求,請求參數都在請求體中。當用戶提交成功后,為了防止用戶刷新瀏覽器頁面造成訂單請求重復提交,我們一般會將用戶重定向到一個顯示訂單的頁面,這樣即使用戶刷新頁面,也不會造成訂單請求重復提交。
大概的代碼就像下面這樣:
@Controller
public class OrderController {
@PostMapping("/order")
public String order(OrderInfo orderInfo) {
//其他處理邏輯
return "redirect:/orderlist";
}
}
這段代碼我相信大家都懂吧!如果不懂可以看看松哥錄制的免費的 SpringMVC 入門教程(硬核!松哥又整了一套免費視頻,搞起!)。
但是這里有一個問題:如果我想傳遞參數怎么辦?
如果是服務器端跳轉,我們可以將參數放在 request 對象中,跳轉完成后還能拿到參數,但是如果是客戶端跳轉我們就只能將參數放在地址欄中了,像上面這個方法的返回值我們可以寫成:return "redirect:/orderlist?xxx=xxx";,這種傳參方式有兩個缺陷:
那該怎么辦?還有辦法傳遞參數嗎?
有!這就是今天松哥要和大家介紹的 flashMap,專門用來解決重定向時參數的傳遞問題。
在重定向時,如果需要傳遞參數,但是又不想放在地址欄中,我們就可以通過 flashMap 來傳遞參數,松哥先來一個簡單的例子大家看看效果:
首先我們定義一個簡單的頁面,里邊就一個 post 請求提交按鈕,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/order" method="post">
<input type="submit" value="提交">
</form>
</body>
</html>
然后在服務端接收該請求,并完成重定向:
@Controller
public class OrderController {
@PostMapping("/order")
public String order(HttpServletRequest req) {
FlashMap flashMap = (FlashMap) req.getAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE);
flashMap.put("name", "江南一點雨");
return "redirect:/orderlist";
}
@GetMapping("/orderlist")
@ResponseBody
public String orderList(Model model) {
return (String) model.getAttribute("name");
}
}
首先在 order 接口中,獲取到 flashMap 屬性,然后存入需要傳遞的參數,這些參數最終會被 SpringMVC 自動放入重定向接口的 Model 中,這樣我們在 orderlist 接口中,就可以獲取到該屬性了。
當然,這是一個比較粗糙的寫法,我們還可以通過 RedirectAttributes 來簡化這一步驟:
@Controller
public class OrderController {
@PostMapping("/order")
public String order(RedirectAttributes attr) {
attr.addFlashAttribute("site", "www.javaboy.org");
attr.addAttribute("name", "微信公眾號:江南一點雨");
return "redirect:/orderlist";
}
@GetMapping("/orderlist")
@ResponseBody
public String orderList(Model model) {
return (String) model.getAttribute("site");
}
}
RedirectAttributes 中有兩種添加參數的方式:
經過前面的講解,現在小伙伴們應該大致明白了 flashMap 的作用了,就是在你進行重定向的時候,不通過地址欄傳遞參數。
很多小伙伴可能會有疑問,重定向其實就是瀏覽器發起了一個新的請求,這新的請求怎么就獲取到上一個請求保存的參數呢?這我們就要來看看 SpringMVC 的源碼了。
首先這里涉及到一個關鍵類叫做 FlashMapManager,如下:
public interface FlashMapManager {
@Nullable
FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);
void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response);
}
兩個方法含義一眼就能看出來:
FlashMapManager 的實現類如下:
從這個繼承類中,我們基本上就能確定默認的保存介質時 session。具體的保存邏輯則是在 AbstractFlashMapManager 類中。
整個參數傳遞的過程可以分為三大步:
第一步,首先我們將參數設置到 outputFlashMap 中,有兩種設置方式:我們前面的代碼 req.getAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE) 就是直接獲取 outputFlashMap 對象然后把參數放進去;第二種方式就是通過在接口中添加 RedirectAttributes 參數,然后把需要傳遞的參數放入 RedirectAttributes 中,這樣當處理器處理完畢后,會自動將其設置到 outputFlashMap 中,具體邏輯在 RequestMappingHandlerAdapter#getModelAndView 方法中:
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
//省略...
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
if (request != null) {
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
}
return mav;
}
可以看到,如果 model 是 RedirectAttributes 的實例的話,則通過 getOutputFlashMap 方法獲取到 outputFlashMap 屬性,然后相關的屬性設置進去。
這是第一步,就是將需要傳遞的參數,先保存到 flashMap 中。
第二步,重定向對應的視圖是 RedirectView,在它的 renderMergedOutputModel 方法中,會調用 FlashMapManager 的 saveOutputFlashMap 方法,將 outputFlashMap 保存到 session 中,如下:
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
HttpServletResponse response) throws IOException {
String targetUrl = createTargetUrl(model, request);
targetUrl = updateTargetUrl(targetUrl, model, request, response);
// Save flash attributes
RequestContextUtils.saveOutputFlashMap(targetUrl, request, response);
// Redirect
sendRedirect(request, response, targetUrl, this.http10Compatible);
}
RequestContextUtils.saveOutputFlashMap 方法最終就會調用到 FlashMapManager 的 saveOutputFlashMap 方法,將 outputFlashMap 保存下來。我們來大概看一下保存邏輯:
public final void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) {
if (CollectionUtils.isEmpty(flashMap)) {
return;
}
String path = decodeAndNormalizePath(flashMap.getTargetRequestPath(), request);
flashMap.setTargetRequestPath(path);
flashMap.startExpirationPeriod(getFlashMapTimeout());
Object mutex = getFlashMapsMutex(request);
if (mutex != null) {
synchronized (mutex) {
List<FlashMap> allFlashMaps = retrieveFlashMaps(request);
allFlashMaps = (allFlashMaps != null ? allFlashMaps : new CopyOnWriteArrayList<>());
allFlashMaps.add(flashMap);
updateFlashMaps(allFlashMaps, request, response);
}
}
else {
List<FlashMap> allFlashMaps = retrieveFlashMaps(request);
allFlashMaps = (allFlashMaps != null ? allFlashMaps : new ArrayList<>(1));
allFlashMaps.add(flashMap);
updateFlashMaps(allFlashMaps, request, response);
}
}
其實這里的邏輯也很簡單,保存之前會給 flashMap 設置兩個屬性,一個是重定向的 url 地址,另一個則是過期時間,過期時間默認 180 秒,這兩個屬性在第三步加載 flashMap 的時候會用到。然后將 flashMap 放入集合中,并調用 updateFlashMaps 方法存入 session 中。
第三步,當重定向請求到達 DispatcherServlet#doService 方法后,此時會調用 FlashMapManager#retrieveAndUpdate 方法從 Session 中獲取 outputFlashMap 并設置到 Request 屬性中備用(最終會被轉化到 Model 中的屬性),相關代碼如下:
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
//省略...
if (this.flashMapManager != null) {
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
}
//省略...
}
注意這里獲取出來的 outputFlashMap 換了一個名字,變成了 inputFlashMap,其實是同一個東西。
我們可以大概看一下獲取的邏輯 AbstractFlashMapManager#retrieveAndUpdate:
public final FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response) {
List<FlashMap> allFlashMaps = retrieveFlashMaps(request);
if (CollectionUtils.isEmpty(allFlashMaps)) {
return null;
}
List<FlashMap> mapsToRemove = getExpiredFlashMaps(allFlashMaps);
FlashMap match = getMatchingFlashMap(allFlashMaps, request);
if (match != null) {
mapsToRemove.add(match);
}
if (!mapsToRemove.isEmpty()) {
Object mutex = getFlashMapsMutex(request);
if (mutex != null) {
synchronized (mutex) {
allFlashMaps = retrieveFlashMaps(request);
if (allFlashMaps != null) {
allFlashMaps.removeAll(mapsToRemove);
updateFlashMaps(allFlashMaps, request, response);
}
}
}
else {
allFlashMaps.removeAll(mapsToRemove);
updateFlashMaps(allFlashMaps, request, response);
}
}
return match;
}
這就是整個獲取 flashMap 的方法,整體來看還是非常 easy 的,并沒有什么難點。
好啦,今天就和小伙伴們分享了一下 SpringMVC 中的 flashMap,不知道大家有沒有在工作中用到這個東西?如果剛好碰到松哥前面所說的需求,用 FlashMap 真的還是蠻方便的。如果需要下載本文案例,小伙伴們可以在公眾號【江南一點雨】后臺回復 20210302,好啦,今天就和大家聊這么多~
標題:了解如何使用 Spring MVC 和 Thymeleaf 創建網頁(來源:Spring中國教育管理中心)
本指南將引導您完成使用 Spring 創建“Hello, World”網站的過程。
您將構建一個具有靜態主頁并且還將接受 HTTP GET 請求的應用程序:http://localhost:8080/greeting。
它將響應一個顯示 HTML 的網頁。HTML 的正文將包含一個問候語:“Hello, World!”
name您可以使用查詢字符串中的可選參數自定義問候語。該 URL 可能是http://localhost:8080/greeting?name=User.
name參數值覆蓋默認值,并通過World內容更改為“Hello,User!”反映在響應中
像大多數 Spring入門指南一樣,您可以從頭開始并完成每個步驟,也可以繞過您已經熟悉的基本設置步驟。無論哪種方式,您最終都會得到工作代碼。
要從頭開始,請繼續從 Spring Initializr 開始。
要跳過基礎知識,請執行以下操作:
完成后,您可以對照中的代碼檢查結果gs-serving-web-content/complete。
您可以使用這個預先初始化的項目并單擊 Generate 下載 ZIP 文件。此項目配置為適合本教程中的示例。
手動初始化項目:
如果您的 IDE 具有 Spring Initializr 集成,您可以從您的 IDE 完成此過程。
你也可以從 Github 上 fork 項目并在你的 IDE 或其他編輯器中打開它。
在 Spring 構建網站的方法中,HTTP 請求由控制器處理。@Controller您可以通過注釋輕松識別控制器。在以下示例中,通過返回 a 的名稱(在本例中GreetingController為 )來處理 GET 請求。A負責呈現 HTML 內容。以下清單(來自)顯示了控制器:/greetingViewgreetingViewsrc/main/java/com/example/servingwebcontent/GreetingController.java
package com.example.servingwebcontent;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class GreetingController {
@GetMapping("/greeting")
public String greeting(@RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {
model.addAttribute("name", name);
return "greeting";
}
}復制
這個控制器簡潔明了,但是有很多事情要做。我們一步一步分解。
@GetMapping注釋確保 HTTP GET 請求/greeting映射到greeting()方法。
@RequestParam將查詢字符串參數的值綁定name到方法的name參數中greeting()。此查詢字符串參數不是required。如果請求中不存在,則使用defaultValueof World。參數的值name被添加到Model對象中,最終使視圖模板可以訪問它。
方法體的實現依賴于視圖技術(在本例中為Thymeleaf)來執行 HTML 的服務器端呈現。Thymeleaf 解析greeting.html模板并評估th:text表達式以呈現${name}在控制器中設置的參數值。以下清單(來自src/main/resources/templates/greeting.html)顯示了greeting.html模板:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'Hello, ' + ${name} + '!'" />
</body>
</html>
確保你的類路徑上有 Thymeleaf(工件坐標:)org.springframework.boot:spring-boot-starter-thymeleaf。它已經存在于 Github 的“初始”和“完整”示例中。
開發 Web 應用程序的一個常見功能是編寫更改代碼、重新啟動應用程序并刷新瀏覽器以查看更改。整個過程會消耗大量時間。為了加快這個刷新周期,Spring Boot 提供了一個方便的模塊,稱為spring-boot-devtools。Spring Boot 開發工具:
Spring Initializr 為您創建了一個應用程序類。在這種情況下,您不需要進一步修改 Spring Initializr 提供的類。以下清單(來自src/main/java/com/example/servingwebcontent/ServingWebContentApplication.java)顯示了應用程序類:
package com.example.servingwebcontent;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ServingWebContentApplication {
public static void main(String[] args) {
SpringApplication.run(ServingWebContentApplication.class, args);
}
}復制
@SpringBootApplication是一個方便的注釋,它添加了以下所有內容:
該main()方法使用 Spring Boot 的SpringApplication.run()方法來啟動應用程序。您是否注意到沒有一行 XML?也沒有web.xml文件。這個 Web 應用程序是 100% 純 Java,您不必處理任何管道或基礎設施的配置。
您可以使用 Gradle 或 Maven 從命令行運行應用程序。您還可以構建一個包含所有必要依賴項、類和資源的單個可執行 JAR 文件并運行它。構建可執行 jar 可以在整個開發生命周期、跨不同環境等中輕松地將服務作為應用程序交付、版本化和部署。
如果您使用 Gradle,則可以使用./gradlew bootRun. 或者,您可以使用構建 JAR 文件./gradlew build,然后運行 ?JAR 文件,如下所示:
java -jar build/libs/gs-serving-web-content-0.1.0.jar
如果您使用 Maven,則可以使用./mvnw spring-boot:run. 或者,您可以使用構建 JAR 文件,./mvnw clean package然后運行該 JAR 文件,如下所示:
java -jar 目標/gs-serving-web-content-0.1.0.jar
此處描述的步驟創建了一個可運行的 JAR。您還可以構建經典的 WAR 文件。
顯示記錄輸出。應用程序應在幾秒鐘內啟動并運行。
現在網站正在運行,請訪問http://localhost:8080/greeting,您應該會看到“Hello, World!”。
通過訪問提供name查詢字符串參數http://localhost:8080/greeting?name=User。注意消息是如何從“Hello, World!”改變的。到“你好,用戶!”:
這一變化表明,@RequestParam安排在GreetingController按預期工作。該name參數已被賦予默認值World,但可以通過查詢字符串顯式覆蓋它。
靜態資源,包括 HTML、JavaScript 和 CSS,可以通過將它們放到源代碼中的正確位置從 Spring Boot 應用程序提供。默認情況下,Spring Boot 從位于/static(或/public) 的類路徑中的資源中提供靜態內容。該index.html資源是特殊的,因為如果它存在,它會被用作“歡迎頁面” "serving-web-content/ which means it is served up as the root resource (that is, at `http://localhost:8080/)。因此,您需要創建以下文件(您可以在 中找到該文件src/main/resources/static/index.html):
<!DOCTYPE HTML>
<html>
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p>Get your greeting <a href="/greeting">here</a></p>
</body>
</html>復制
重新啟動應用程序時,您將看到 HTML 位于http://localhost:8080/.
恭喜!您剛剛使用 Spring 開發了一個網頁。
#程序員#
活就像海洋,只有意志堅強的人才能到達彼岸。
已經很久沒有發文章了呀,想必大家都掛念我了,哈哈。
溫故而知新,今天一起來復習一下spring mvc的內容吧。
spring mvc簡介與運行原理
Spring的模型-視圖-控制器(MVC)框架是圍繞一個DispatcherServlet來設計的,這個Servlet會把請求分發給各個處理器,并支持可配置的處理器映射、視圖渲染、本地化、時區與主題渲染等,甚至還能支持文件上傳。
原理.png
主要注解
spring mvc注解.png
ContextLoaderListener
在講ContextLoaderListener之前,首先來了解一下web.xml的作用。
web.xml加載過程.png
而spring mvc啟動過程大致分為兩個過程:
web.xml配置.png
其中ContextLoaderListener監聽器它實現了ServletContextListener這個接口,在web.xml配置這個監聽器,啟動容器時,就會默認執行它實現的方法。在ContextLoaderListener中關聯了ContextLoader這個類,所以整個加載配置過程由ContextLoader來完成。
<!-- 配置contextConfigLocation初始化參數 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <!-- 配置ContextLoaderListerner --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
ServletContextListener 接口有兩個方法:contextInitialized,contextDestroyed
DispatcherServlet
Spring MVC框架,與其他很多web的MVC框架一樣:請求驅動;所有設計都圍繞著一個中央Servlet來展開,它負責把所有請求分發到控制器;同時提供其他web應用開發所需要的功能。不過Spring的中央處理器,DispatcherServlet,能做的比這更多。
下圖展示了Spring Web MVC的DispatcherServlet處理請求的工作流。熟悉設計模式的朋友會發現,DispatcherServlet應用的其實就是一個“前端控制器”的設計模式(其他很多優秀的web框架也都使用了這個設計模式)。
spring mvc處理請求的流程.jpg
<!-- servlet定義 --> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
其中
在Spring MVC中,每個DispatcherServlet都持有一個自己的上下文對象WebApplicationContext,它又繼承了根(root)WebApplicationContext對象中已經定義的所有bean。這些繼承的bean可以在具體的Servlet實例中被重載,在每個Servlet實例中你也可以定義其scope下的新bean。
WebApplicationContext繼承自ApplicationContext,它提供了一些web應用經常需要用到的特性。它與普通的ApplicationContext不同的地方在于,它支持主題的解析,并且知道它關聯到的是哪個servlet(它持有一個該ServletContext的引用)
DispatcherServlet繼承結構
spring mvc同時提供了很多特殊的注解,用于處理請求和渲染視圖等。DispatcherServlet初始化的過程中會默認使用這些特殊bean進行配置。如果你想指定使用哪個特定的bean,你可以在web應用上下文WebApplicationContext中簡單地配置它們。
特殊bean.png
其中,常用的ViewResolver的配置。以jsp作為視圖為例
<!-- 對模型視圖名稱的解析,即在模型視圖名稱添加前后綴 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean>
配置上傳文件限制MultipartResolver
<!-- 上傳限制 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 上傳文件大小限制為31M,31*1024*1024 --> <property name="maxUploadSize" value="32505856"/> </bean>
applicationContext.xml中的標簽
applicationContext.xml配置文件標簽.png
文件上傳
前面說到DispatcherServlet中有個特殊的Bean叫MultipartResolver,可用于限制文件的上傳大小等。當解析器MultipartResolver完成處理時,請求便會像其他請求一樣被正常流程處理。
<form method="post" action="/form" enctype="multipart/form-data"> <input type="text" name="name"/> <input type="file" name="file"/> <input type="submit"/> </form>
@RequestMapping(path="/form", method=RequestMethod.POST)
public String handleFormUpload(@RequestParam("name") String name,
@RequestParam("file") MultipartFile file) {
if (!file.isEmpty()) {
byte[] bytes=file.getBytes();
// store the bytes somewhere
return "redirect:uploadSuccess";
}
return "redirect:uploadFailure";
}
異常處理
先來說下常見的異常處理有幾種方式,如下圖:
異常處理方式.png
Spring的處理器異常解析器HandlerExceptionResolver接口的實現負責處理各類控制器執行過程中出現的異常。也是上面提到的,是DispatcherServlet中的特殊bean,可以自定義配置處理。
某種程度上講,HandlerExceptionResolver與你在web應用描述符web.xml文件中能定義的異常映射(exception mapping)很相像,不過它比后者提供了更靈活的方式。比如它能提供異常被拋出時正在執行的是哪個處理器這樣的信息。
public interface HandlerExceptionResolver { ModelAndView resolveException( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex); }
@ExceptionHandler(Exception.class) public Object exceptionHandler(Exception ex, HttpServletResponse response, HttpServletRequest request) throws IOException { String url=""; String msg=ex.getMessage(); Object resultModel=null; try { if (ex.getClass()==HttpRequestMethodNotSupportedException.class) { url="admin/common/500"; System.out.println("--------毛有找到對應方法---------"); } else if (ex.getClass()==ParameterException.class) {//自定義的異常 } else if (ex.getClass()==UnauthorizedException.class) { url="admin/common/unauth"; System.out.println("--------毛有權限---------"); } String header=req.getHeader("X-Requested-With"); boolean isAjax="XMLHttpRequest".equalsIgnoreCase(header); String method=req.getMethod(); boolean isPost="POST".equalsIgnoreCase(method); if (isAjax || isPost) { return Message.error(msg); } else { ModelAndView view=new ModelAndView(url); view.addObject("error", msg); view.addObject("class", ex.getClass()); view.addObject("method", request.getRequestURI()); return view; } } catch (Exception exception) { logger.error(exception.getMessage(), exception); return resultModel; } finally { logger.error(msg, ex); ex.printStackTrace(); } }
<!-- 默認的錯誤處理頁面 --> <error-page> <error-code>403</error-code> <location>/403.html</location> </error-page> <error-page> <error-code>404</error-code> <location>/404.html</location> </error-page> <!-- 僅僅在調試的時候注視掉,在正式部署的時候不能注釋 --> <!-- 這樣配置也是可以的,表示發生500錯誤的時候,轉到500.jsp頁面處理。 --> <error-page> <error-code>500</error-code> <location>/500.html</location> </error-page> <!-- 這樣的配置表示如果jsp頁面或者servlet發生java.lang.Exception類型(當然包含子類)的異常就會轉到500.jsp頁面處理。 --> <error-page> <exception-type>java.lang.Exception</exception-type> <location>/500.jsp</location> </error-page> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/500.jsp</location> </error-page> <!-- 當error-code和exception-type都配置時,exception-type配置的頁面優先級高及出現500錯誤,發生異常Exception時會跳轉到500.jsp-->
解答:如果resolveException返回了ModelAndView,會優先根據返回值中的頁面來顯示。不過,resolveException可以返回null,此時則展示web.xml中的error-page的500狀態碼配置的頁面。
當web.xml中有相應的error-page配置,則可以在實現resolveException方法時返回null。
API文檔中對返回值的解釋:
** return a corresponding ModelAndView to forward to, or null for default processing.**
寫在最后
、
歡迎大家關注,后期文章一定更加精彩
*請認真填寫需求信息,我們會在24小時內與您取得聯系。