異常
@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
方法相同的返回值。