本篇介紹Spring Boot/Spring Web MVC的@ControllerAdvice
annotation的用法。
@ControllerAdvice
是在Spring 3.2新增的annotation,可以用來攔截並處理應用程式中全部Controller所拋出的Exception例外錯誤。其也是@Component
,所以會被Spring scan為Bean。
以下是@ControllerAdvice
的簡單範例。
環境如下:
- macOS High Sierra
- Java 1.8
- IntelliJ IDEA 2019.2.1(Community Edition)
- Spring Boot 2.1.3.RELEASE
首先建立一個Spring Boot專案 (Eclipse參考, IntelliJ IDEA參考)。
Spring Boot專案配置檔application.properties
設定如下。
application.properties
#context path
server.servlet.context-path=/demo
#port
server.port=8080
所以應用程式在本機的連結路徑為http://localhost:8080/demo
。
新增一個自訂的Exception類DemoException
,繼承RuntimeException
。此例外類別待會測試時會被拋出並被下面的DemoExceptionHandler
處理。
DemoException
package com.abc.demo.exception;
public class DemoException extends RuntimeException {
private String errorCode;
private String errorMessage;
public DemoException(String errorCode, String errorMessage) {
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}
// getters and setters
}
新增一個用來處理應用程式例外的類別DemoExceptionHandler
,在類別名稱前掛上@ControllerAdvice
注釋,因此應用程式拋出的所有例外都可被此類別攔截。
在DemoExceptionHandler
中定義一個方法,在方法前掛上@ExceptionHandler
,其value
設為DemoException.class
,則此方法即可處理被拋出的DemoException
。
DemoExceptionHandler
package com.abc.demo.exception.handler;
import com.abc.demo.exception.DemoException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class DemoExceptionHandler {
@ExceptionHandler({DemoException.class}) // <--
public final void handleDemoException(DemoException ex) {
System.out.println("handle DemoException...");
System.out.println("error code:" + ex.getErrorCode());
System.out.println("error message:" + ex.getErrorMessage());
}
// by 菜鳥工程師肉豬
}
最後建立一個DemoController
類用用來測試DemoExceptionHandler
處理例外的效果。
DemoController.hello()
被調用時會直接拋出DemoException
;
DemoController.getMessagesByDate()
如果輸入參數非定義的日期格式也會拋出DemoException
。
DemoController
package com.abc.demo.controller;
import com.abc.demo.exception.DemoException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
@RestController
public class DemoController {
@GetMapping("/hello")
public String hello() {
System.out.println("hello");
throw new DemoException("9999", "test");
}
@GetMapping("/message/{dateStr}")
public List<String> getMessagesByDate(@PathVariable String dateStr) {
System.out.println(dateStr);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
sdf.parse(dateStr);
} catch (ParseException e) {
throw new DemoException("1003", "wrong format");
}
// 其他邏輯 by 菜鳥工程師肉豬
return new ArrayList<>();
}
}
接著啟動專案,在瀏覽器位址輸入http://localhost:8080/demo/hello
來發出請求給DemoController.hello()
。該方法內拋出的DemoException
會由DemoExceptionHandler.handleDemoException()
處理,所以會在console印出以下結果。
hello
handle DemoException...
error code:9999
error message:test
在瀏覽器位址輸入http://localhost:8080/demo/message/201901231
來發出請求給DemoController.getMessageByDate()
。由於傳入的日期格式不符pattern,所以會先拋出ParseException
並被try catch
捕捉,然後才拋出自訂的DemoException
,最後由DemoExceptionHandler.handleDemoException()
處理,所以會在console印出以下結果。
201901231
handle DemoException...
error code:1003
error message:wrong format
專案src/main
目錄結構如下。
沒有留言:
張貼留言