背景:
最近在工作中对接权限中台服务,采用他们的服务对我们方法级别的接口进行权限控制。权限中台对方法级别进行权限控制是采用注解@access 形式进行控制的。结果我发现,某个方法在某个用户没有权限访问的时候会抛出异常。对于这样的异常,我们该如何去处理。由于在异常是在注解上报出来的,不能使用传统的try-catch 去处理。
这个时候就可以使用@ControllerAdvice+ @ExceptionHandler注解进行全局的Controller层异常处理。
功能介绍
@ExceptionHandler:统一处理某一类异常,从而能够减少代码重复率和复杂度
@ControllerAdvice:异常集中处理,更好的使业务逻辑与异常处理剥离开
@ResponseStatus:可以将某种异常映射为HTTP状态码
@ExceptionHandler:
当一个Controller中有方法加了@ExceptionHandler之后,这个Controller其他方法中没有捕获的异常就会以参数的形式传入加了@ExceptionHandler注解的那个方法中。
@ControllerAdvice:
该注解作用对象为TYPE,包括类、接口和枚举等,在运行时有效,并且可以通过Spring扫描为bean组件。其可以包含由@ExceptionHandler、@InitBinder 和@ModelAttribute标注的方法,可以处理多个Controller类,这样所有控制器的异常可以在一个地方进行处理。
注:如果单使用@ExceptionHandler,只能在当前Controller中处理异常。但当配合@ControllerAdvice一起使用的时候,就可以摆脱那个限制,对所有controller层异常进行处理。
实例
下面的例子可以对所有的controller类添加了@RestCotrller标签的,并且方法会抛出AllocatorOperateException和MethodArgumentNotValidException异常的都会捕获。
/**
* 项目中使用的controller advice 主要处理一些异常
*
*
*/
@ControllerAdvice(annotations = RestController.class)
public class ArcControllerAdvice {
private static final Logger LOG = LoggerFactory.getLogger(ArcControllerAdvice.class);
/**
* 处理AllocatorOperateException异常
*
* @param e
* @return
*/
@ExceptionHandler(AllocatorOperateException.class)
public ResponseEntity<Result<Void>> handleAllocatorException(
final AllocatorOperateException e) {
LOG.error("handleAllocatorException", e);
return ResponseEntity.ok(Result.error(e.getMessage()));
}
/**
* 处理 MethodArgumentNotValidException异常
*
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Result<Void>> handleMethodArgumentNotValidException(
final MethodArgumentNotValidException e) {
final String msg = e.getBindingResult().getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(","));
LOG.error("handleMethodArgumentNotValidException", e);
return ResponseEntity.ok(Result.error(msg));
}
}
参考:https://blog.csdn.net/Abysscarry/article/details/80400140