@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项目