在做web应用时,请求处理中经常遇到错误发生错误,处理方式可以再每个controller方法中添加try…catch…处理,但是这样代码非常冗余,在springboot中使用@ControllerAdvice注解可实现全局异常捕获,就不用每个controller都写try…catch…了
一.具体使用方法
1.错误信息封装类
@Data
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(
value = {"hibernateLazyInitializer", "handler", "fieldHandler"},
ignoreUnknown = true
)
public class ErrorEntity implements Serializable {
private static final long serialVersionUID = 3550224421750657701L;
@JsonProperty("code")
private String code;
@JsonProperty("msg")
private String msg;
private Object data;
@JsonProperty("details")
private Object details;
public ErrorEntity(RestStatus statusCodes) {
this(statusCodes, (Object)null);
}
public ErrorEntity(RestStatus statusCodes, Object details) {
this.code = statusCodes.code();
this.msg = statusCodes.message();
if(details != null) {
this.details = details;
}
}
}
2. 全局异常处理类
@Slf4j
@ControllerAdvice
public class FaultBarrier {
// 处理 Exception 异常,从Request域取出对应错误信息, 封装成实体ErrorEntity后转换成JSON输出
@ResponseBody
@ExceptionHandler(value = Exception.class)
public ResponseEntity exceptionHandler(HttpServletRequest httpServletRequest, Exception e) {
logger.error("服务错误:", e);
final ErrorEntity error = new ErrorEntity(status);
return error;
}
}
3.controller使用
以前的写法:
@PostMapping(value = "/select")
public ErrorEntity select(@RequestBody Map map) {
ErrorEntity ee = new ResponseEntity()
try {
...业务处理
} catch (Exception e) {
log.error(e);
ee.setCode("xxxxx");
ee.setMsg("服务错误:" + e);
return ee;
}
}
现在的写法:
@PostMapping(value = "/select")
public ErrorEntity select(@RequestBody Map map) {
ErrorEntity ee = new ResponseEntity()
...业务处理
return ee;
}
}
由上面看出,使用全局异常处理类代码简洁的很多
4.抛异常
遇到异常时,使用throw new ErrorEntry(“1111”,“参数不能为空”)或 直接return这个错误类即可
5.错误返回结果
二.注解讲解
@ControllerAdvice : 定义该类为全局异常处理类,可以指定处理的controller范围:
- basePackages:指定一个或多个包,这些包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理
@ControllerAdvice(basePackages = {"com.tfjybj.intern.provider.controller"})
public class FaultBarrier{}
- basePackageClasses:是 basePackages 的一种变形,指定一个或多个 Controller 类,这些类所属的包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理
@ControllerAdvice(basePackageClasses = {Test.class})
public class FaultBarrier{}
- assignableTypes:指定一个或多个 Controller 类,这些类被该 @ControllerAdvice 管理
@ControllerAdvice(assignableTypes= {Test.class})
public class FaultBarrier{}
- annotations:指定一个或多个注解,被这些注解所标记的 Controller 会被该 @ControllerAdvice 管理
@ControllerAdvice(annotations = {RestController.class})
public class FaultBarrier{}
@ExceptionHandler: 定义该方法为异常处理方法。value 的值为需要处理的异常类的 class 文件。在例子中,方法传入两个参数。一个是对应的 Exception 异常类,一个是 HttpServletRequest 类。当然,除了这两种参数,还支持传入一些其他参数。
三.优点
减少代码冗余
四.缺点
只能处理 controller 层抛出的异常,对例如 Interceptor(拦截器)层的异常、定时任务中的异常、异步方法中的异常,不会进行处理