異常

@Controller@ControllerAdvice 類可以有 @ExceptionHandler 方法來處理來自控制器方法的異常。以下示例包含這樣一個處理方法

  • Java

  • Kotlin

import java.io.IOException;

import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;

@Controller
public class SimpleController {

	@ExceptionHandler(IOException.class)
	public ResponseEntity<String> handle() {
		return ResponseEntity.internalServerError().body("Could not read file storage");
	}

}
import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.ExceptionHandler
import java.io.IOException

@Controller
class SimpleController {

	@ExceptionHandler(IOException::class)
	fun handle() : ResponseEntity<String> {
		return ResponseEntity.internalServerError().body("Could not read file storage")
	}
	
}

異常可以匹配正在傳播的頂級異常(即直接丟擲的 IOException)或頂級包裝異常內的直接原因(例如,包裝在 IllegalStateException 中的 IOException)。

對於匹配的異常型別,最好將目標異常宣告為方法引數,如前例所示。或者,註解宣告可以縮小要匹配的異常類型範圍。我們通常建議在引數簽名中儘可能具體,並在具有相應順序優先順序的 @ControllerAdvice 上宣告主要根異常對映。有關詳細資訊,請參閱 MVC 部分

WebFlux 中的 @ExceptionHandler 方法支援與 @RequestMapping 方法相同的方法引數和返回值,但請求體和 @ModelAttribute 相關的方法引數除外。

Spring WebFlux 中對 @ExceptionHandler 方法的支援由 @RequestMapping 方法的 HandlerAdapter 提供。有關更多詳細資訊,請參閱 DispatcherHandler

媒體型別對映

除了異常型別,@ExceptionHandler 方法還可以宣告可產生的媒體型別。這允許根據 HTTP 客戶端請求的媒體型別(通常在 "Accept" HTTP 請求頭中)來精細化錯誤響應。

應用程式可以直接在註解上宣告可產生的媒體型別,對於相同的異常型別

  • Java

  • Kotlin

@ExceptionHandler(produces = "application/json")
public ResponseEntity<ErrorMessage> handleJson(IllegalArgumentException exc) {
	return ResponseEntity.badRequest().body(new ErrorMessage(exc.getMessage(), 42));
}

@ExceptionHandler(produces = "text/html")
public String handle(IllegalArgumentException exc, Model model) {
	model.addAttribute("error", new ErrorMessage(exc.getMessage(), 42));
	return "errorView";
}
@ExceptionHandler(produces = ["application/json"])
fun handleJson(exc: IllegalArgumentException): ResponseEntity<ErrorMessage> {
	return ResponseEntity.badRequest().body(ErrorMessage(exc.message, 42))
}

@ExceptionHandler(produces = ["text/html"])
fun handle(exc: IllegalArgumentException, model: Model): String {
	model.addAttribute("error", ErrorMessage(exc.message, 42))
	return "errorView"
}

在這裡,方法處理相同的異常型別,但不會被拒絕為重複。相反,請求 "application/json" 的 API 客戶端將接收到 JSON 錯誤,瀏覽器將獲得 HTML 錯誤檢視。每個 @ExceptionHandler 註解可以宣告多個可產生的媒體型別,錯誤處理階段的內容協商將決定使用哪種內容型別。

方法引數

@ExceptionHandler 方法支援與 @RequestMapping 方法相同的方法引數,只是請求體可能已經被消費。

返回值

@ExceptionHandler 方法支援與 @RequestMapping 方法相同的返回值