正常來說一個系統肯定有很多業務異常。而這些業務異常的信息如何返回給前台呈現給用戶。比如用戶的某些操作不被允許,需要給用戶提示。
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項目