@ControllerAdvice自定義異常統一處理
正常來說一個系統肯定有很多業務異常。而這些業務異常的資訊如何返回給前臺呈現給使用者。比如使用者的某些操作不被允許,需要給使用者提示。
Spring 提供了@ControllerAdvice這個註解,這個註解可以實現全域性異常處理,全域性資料繫結,全域性資料預處理,這裡主要說下使用這個註解實現全域性異常處理。
1.定義我們自己的業務異常ErrorCodeException
package com.nijunyang.exception.exception; /** * Description: * Created by nijunyang on 2019/12/20 9:36 */ public class ErrorCodeException extends RuntimeException { private int code; /** * 用於填充資原始檔中佔位符 */ private Object[] args; public ErrorCodeException(int code, Object... args) { this.code = code; this.args = args; } public int getCode() { return code; } public Object[] getArgs() { return args; } }
2.編寫統一異常處理器RestExceptionHandler,使用@ControllerAdvice註解修飾,在異常處理器編寫針對某個異常的處理方法,使用@ExceptionHandler註解指向某個指定異常。當代碼中拋了該異常就會進入此方法執行,從而返回我們處理後的資訊給請求者。
3.資原始檔放置提示資訊,根據錯誤碼去匹配提示資訊。
package com.nijunyang.exception.handler; import com.nijunyang.exception.exception.ErrorCodeException; import com.nijunyang.exception.model.RestErrorResponse; import com.nijunyang.exception.model.Status; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import javax.annotation.Resource; import java.io.File; import java.io.IOException; import java.util.Locale; /** * Description: 控制層統一異常處理 * Created by nijunyang on 2019/12/20 9:33 */ @ControllerAdvice public class RestExceptionHandler { @Autowired private MessageSource messageSource; //locale可以處理國際化資原始檔,不同的語言 @ExceptionHandler(value = ErrorCodeException.class) public final ResponseEntity<RestErrorResponse> handleBadRequestException(ErrorCodeException errorCodeException, Locale locale) { String message = messageSource.getMessage(String.valueOf(errorCodeException.getCode()), errorCodeException.getArgs(), locale); RestErrorResponse restErrorResponse = new RestErrorResponse(Status.FAILED, errorCodeException.getCode(), message); return new ResponseEntity<>(restErrorResponse, HttpStatus.OK); } }
4.配置檔案指向資原始檔位置(spring.messages.basename=xxx)
spring.messages.basename指向資源的字首名字就行了,後面的國家語言標誌不需要,Locale會根據系統的語言去識別,資原始檔需要配置一個預設的(messages.properties),不然啟動的時候可能無法正常注入資源,因為預設的是去載入不帶國家語言標誌的檔案。
當然字首隨便配置什麼都可以 只要再springboot的配置檔案spring.messages.basename的路徑配置正確就行,就像這樣子也是可以的
5.控制層模擬異常丟擲:
package com.nijunyang.exception.controller; import com.nijunyang.exception.exception.ErrorCodeException; import com.nijunyang.exception.model.ErrorCode; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * Description: * Created by nijunyang on 2019/12/20 9:58 */ @RestController @RequestMapping("/error") public class Controller { @GetMapping("/file") public ResponseEntity test() { //模擬檔案不存在 String path = "a/b/c/d.txt"; throw new ErrorCodeException(ErrorCode.FILE_DOES_NOT_EXIST_51001, path); } }
6.前臺呼叫結果
z/b/c/d.txt就去填充了資原始檔中的佔位符
錯誤碼:
package com.nijunyang.exception.model; /** * Description: * Created by nijunyang on 2020/1/20 20:28 */ public final class ErrorCode { public static int FILE_DOES_NOT_EXIST_51001 = 51001; }
結果狀態:
package com.nijunyang.exception.model; /** * Description: * Created by nijunyang on 2019/12/20 10:21 */ public enum Status { SUCCESS, FAILED }
異常統一結果返回物件
package com.nijunyang.exception.model; /** * Description: * Created by nijunyang on 2019/12/20 9:38 */ public class RestErrorResponse { private Status status; /** * 錯誤碼 */ private Integer errorCode; /** * 錯誤資訊 */ private String errorMsg; public RestErrorResponse(Status status, Integer errorCode, String errorMsg) { this.errorCode = errorCode; this.errorMsg = errorMsg; this.status = status; } public Integer getErrorCode() { return errorCode; } public void setErrorCode(Integer errorCode) { this.errorCode = errorCode; } public String getErrorMsg() { return errorMsg; } public void setErrorMsg(String errorMsg) { this.errorMsg = errorMsg; } public Status getStatus() { return status; } }
pom檔案依賴:springBoot版本是2.1.7.RELEASE
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> </dependency> </dependencies>
完整程式碼:https://github.com/bluedarkni/study.git ---->springboot--->exception項