相信很多同学都跟我一样写过这样的代码:
这是一个在java控制器中处理异常的样例,运行起来也没什么问题。唯一的问题就是这有点复杂,这方法会有两种返回值,正常的和异常的,但其实我们通常只想关注正常的,像下面那样:
干净多了,但是异常情况怎么处理呢?spring为我们提供了一个非常方便的异常处理方案:控制器通知(controller advice),这其实是将所有的控制器作为一个切面,利用切片技术来实现的。
控制器通知
控制器通知是一个带有@ControllerAdvice注解的类,这个类会带有一个或多个如下方法:
- @ExceptionHandler注解方法
- @InitBinder注解方法
- @ModelAttribute注解方法
这些方法会运用到所有注解了@RequestMapping的方法中,也就是所有控制器方法中,@ControllerAdvice最实用的场景就是将所有@ExceptionHandler收集到一个类中统一处理,代码如下:
@ControllerAdvice
@ResponseBody
public class ExceptionAdvice {
// 日志
Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class);
/**
* 将异常在Controller捕获转换成Result对象返回
* @param ex
* @see Result
*/
@ExceptionHandler(Exception.class)
public Result handleAllException(Exception ex){
logger.error("ExceptionAdvice.handleAllException",ex);
// 返回统一的error Result
return Result.getErrorResult();
}
/**
* 处理ConstraintViolationException
* @param ex
* @return
*/
@ExceptionHandler(ConstraintViolationException.class)
public Result handleConstraintViolationException(ConstraintViolationException ex){
Set<ConstraintViolation<?>> violations = ex.getConstraintViolations();
ConstraintViolation<?> violation = violations.iterator().next();
String message = violation.getMessage();
logger.error("ExceptionAdvice.handleConstraintViolationException=>{}",message,ex);
return Result.getErrorResult();
}
}
任意方法中抛出ConstraintViolationException(参数验证异常)都会调用handleConstraintViolationException方法进行处理,统一返回异常信息;抛出Exception会调用handleAllException方法返回。业务代码中就不必可以处理异常信息了,除非是一些个性化的异常需要特别处理。