Spring MVC 是 Spring Framework 中以 Servlet 為基礎的 Web 框架。其前端控制器 DispatcherServlet 協調請求映射、引數解析、控制器呼叫、回傳值處理與例外轉譯。Spring WebFlux 使用不同的反應式執行階段與執行緒模型;不能將兩個框架視為可互換。
引導與分派 #
非 Boot 的 Servlet 應用程式可以透過 WebApplicationInitializer 註冊 Web 應用程式上下文與分派器:
public final class WebInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) {
var context = new AnnotationConfigWebApplicationContext();
context.register(WebConfiguration.class);
var servlet = servletContext.addServlet(
"mvc", new DispatcherServlet(context));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
}Spring Boot 對 MVC 應用程式執行等效註冊。將分派器映射至 / 讓 Servlet 容器保留對靜態資源與 JSP 的特殊處理;/* 也會擷取那些分派。
對每個請求,分派器會:
- 向有順序的
HandlerMapping實作要求處理常式與攔截器; - 選取能呼叫該處理常式的
HandlerAdapter; - 呼叫前處理攔截器與處理常式;
- 將回傳值處理為回應本文、檢視、非同步結果或其他支援形式;以及
- 執行例外解析器與完成攔截器。
MVC 策略物件是分派器上下文中的 Bean。@EnableWebMvc 為純 Spring 應用程式匯入標準設定。在 Spring Boot 中,請實作 WebMvcConfigurer 來擴充 Boot 設定,而不要加入會完全接管自動設定的 @EnableWebMvc。
請求映射、繫結與驗證 #
帶註解的控制器會依路徑、HTTP 方法、參數、標頭、消費的媒體型別與產生的媒體型別進行映射:
@PostMapping(
path = "/orders",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<OrderView> create(@Valid @RequestBody CreateOrder request) {
return ResponseEntity.status(HttpStatus.CREATED)
.body(orderService.create(request));
}HandlerMethodArgumentResolver 實作提供路徑變數、查詢參數、標頭、Cookie、主體、Servlet 物件、模型屬性與請求本文。簡單文字值使用轉換與格式化。@ModelAttribute 透過 WebDataBinder 繫結具名屬性;請定義允許欄位或使用專用命令型別,因為繫結是輸入安全邊界。@RequestBody 則將媒體解碼委派給 HttpMessageConverter。
@Valid 套用 Jakarta Bean Validation,而 @Validated 還能選取驗證群組。對模型屬性繫結而言,緊接在已繫結引數後的 BindingResult 引數可讓控制器檢查轉換與驗證錯誤。沒有區域處理時,MVC 會透過例外解析鏈轉譯驗證例外。
回傳值與內容協商 #
HandlerMethodReturnValueHandler 實作會處理 ModelAndView、檢視名稱、ResponseEntity、ProblemDetail 以及標註 @ResponseBody 的物件等值。回應本文值由 HttpMessageConverter 編碼。
內容協商會比較處理常式的 produces 條件、請求可接受的媒體型別與轉換器能力。具有不支援 Content-Type 的請求本文會產生 415;沒有可接受的回應表示會產生 406。相較於路徑副檔名協商,優先使用 Accept 標頭與明確的預設值。
例外解析 #
HandlerExceptionResolver 將失敗轉為模型、狀態或回應。標準註解設定包括:
ExceptionHandlerExceptionResolver,處理控制器與@ControllerAdvice例外方法;ResponseStatusExceptionResolver,處理@ResponseStatus與ResponseStatusException;以及DefaultHandlerExceptionResolver,處理框架例外。
集中式 advice 應將網域失敗映射至穩定的狀態碼與一致的錯誤綱要。Spring Framework 6 引入 ProblemDetail 與 ErrorResponse;Spring 6.1 文件依據 RFC 9457 描述其 problem-details 支援,而 RFC 9457 已取代 RFC 7807。
執行緒、非同步請求與上下文 #
同步 MVC 處理會在 Servlet 容器執行緒上執行。阻塞的資料庫或 HTTP 呼叫會保留該執行緒直到完成,因此要從連接器一路到每個下游相依性設定期限與容量。
控制器可以回傳 Callable、DeferredResult 或 WebAsyncTask。MVC 會啟動 Servlet 非同步處理、釋放容器執行緒,並在結果準備好時執行後續的 ASYNC 分派。非同步 MVC 不會讓阻塞程式碼變成非阻塞;它會將工作移至另一個執行器。請明確設定該執行器、逾時、取消與超載行為。
執行緒區域的記錄、地區設定、安全與觀測狀態不會自動跟隨任意執行器工作。請使用受支援的攔截器或工作裝飾器,或明確傳遞上下文,並一律清除已還原的狀態。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)