例外

@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 方法相同的方法引數和回傳值,但與請求 Body 和 @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 方法相同的方法引數,但請求 Body 可能已被消耗。

回傳值

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