自定義 Spring Boot 預設返回的 http 狀態碼
ResponseEntity?
用法: 作為方法的返回類型
用途: 自定義回傳的http response 的細節
預設是 200 OK
在下面自定義後 ,就變成了 200 ACCEPTED
@RestController
public class MyController5 {
@RequestMapping("/test")
public ResponseEntity<String> test() {
return ResponseEntity.status(HttpStatus.ACCEPTED).body("Hellow World");
}
}
@ControllerAdvice + @ExceptionHandler
定義每個Exception 所返回的 http response
@ControllerAdvice
用法: 只能加在 class 上
用途: 將這個class 變成一個bean ,並且可以在內部使用 @ExceptionHandler
@ExceptionHandler
用法: 只能加在 方法上
用途: 去 catch 方法所噴出的 Exception
Throwable 底下
| Error | 系統錯誤 ,不需處理 |
| Exception | 程式錯誤 ,需要處理 |
digraph hierarchy {
nodesep=1.0 // increases the separation between nodes
node [color=Black,fontname=Courier,shape=box] //All nodes will this shape and colour
edge [color=Red, style=dashed] //All the lines look like this
Throwable->{Error Exception}
Error->{OutOFMemoryError }
Exception->{RuntimeException IOException}
RuntimeException->{IllegalArgumentException }
}
練習
@RestController
public class MyController6 {
@RequestMapping("/test")
public String test() {
throw new RuntimeException("test error");
}
}
自定義 RuntimeException 所返回的 http response
package com.example.demo;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handle(RuntimeException exception){
/* 當 Controller 裡面的任何一個方法去噴出 RuntimeException 的時候
* 這個 @ExceptionHandler 他就會將 這個 RuntimeException 給接住
* 所以可以在這個 handle() 方法中去定義說要返回的 http response 給前端
*/
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("RuntimeException: " + exception.getMessage());
}
}
Talend API Tester
GET http://localhost:8080/test


練習2
@RestController
public class MyController6 {
@RequestMapping("/test")
public String test() {
throw new RuntimeException("test error");
}
@RequestMapping("/test2")
public String test2() {
throw new IllegalArgumentException("test2 error");
}
}
package com.example.demo;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handle(RuntimeException exception){
return ResponseEntity
.status(HttpStatus.SERVICE_UNAVAILABLE)
.body("RuntimeException: " + exception.getMessage());
}
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handle(IllegalArgumentException exception){
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body("IllegalArgumentException: " + exception.getMessage())
}
}
Talend API Tester
GET http://localhost:8080/test2

如果沒有用 @ExceptionHandler 對 throw new IllegalArgumentException
則Spring Boot 會透過繼承關係 ,去找IllegalArgumentException 所繼承的class ,找到對應的 @ExceptionHandler
@RestController
public class MyController6 {
@RequestMapping("/test")
public String test() {
throw new RuntimeException("test error");
}
@RequestMapping("/test2")
public String test2() {
throw new IllegalArgumentException("test2 error");
}
}
package com.example.demo;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handle(RuntimeException exception){
return ResponseEntity
.status(HttpStatus.SERVICE_UNAVAILABLE)
.body("RuntimeException: " + exception.getMessage());
}
}
由此可以看出 public class IllegalArgumentException extends RuntimeException
他跳503 ,是因為上一層是 RuntimeException

使用 @ControllerAdvice 的好處: 統一管理 Exception
可以不用一直重複寫 try…catch
@RestController
public class MyController6 {
@RequestMapping("/test")
public String test() {
try{
throw new RuntimeException("test error");
}catch(RuntimeException e){
return e.getMessage();
}
}
}
底層由 Spring AOP 所實作
@ControllerAdvice 可以想像成 專門在處理大家所噴出的 Exception 的切面