将异常映射为 HTTP 状态码
Spring 中部分异常会自动映射到合适的状态码,但是对于应用抛出的异常无能为力。
可以通过@ResponseStatus注解将异常映射为合适的 HTTP 状态码。
@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Spittle Not Found")
public class SpittleNotFoundException extends RuntimeException {}类似上述代码,将自定义的SpittleNotFoundException异常类映射到 404。
处理异常
一般的异常处理会在try...catch..中实现,但是这样代码耦合度较高。将异常处理剥离出来形成如下代码:
@ExceptionHandler(DuplicateSpittleException.class)
public String handleDuplicateSpittle() {
return "error/duplicate";
}使用@ExceptionHandler注解,当抛出DuplicateSpittleException异常时会委托该方法处理。但是只能处理当前Controller中的异常,如果想要同时处理多个Controller类中抛出的异常,可以使用 Controller Advice,下面会介绍用法。
Controller Advice
控制器通知指的是带有@ControllerAdvice注解的类,其中包含了要在多个Controller类之间共享的方法,这些方法必须是如下类型:
@ExceptionHandler注解标注的方法:用于捕获Controller中抛出的不同类型的异常,从而达到异常全局处理的目的。@InitBinder注解标注的方法:用于请求中注册自定义参数的解析,从而达到自定义请求参数格式的目的。@ModelAttribute注解标注的方法:表示此方法会在执行目标Controller方法之前执行。
@ControllerAdvice注解本身已经使用了@Component,因此@ControllerAdvice注解所标注的类将会自动被组件扫描获取到并注册。
下面是示例代码:
@ControllerAdvice
public class AppWideExceptionHandler {
@ExceptionHandler(DuplicateSpittleException.class)
public String handleNotFound() {
return "error/duplicate";
}
}当Controller抛出的某个异常多个@ExceptionHandler标注的方法都适用时,Spring 会选择最具体的异常处理方法来处理,也就是从子类向父类依次选择。因此可以定义一个@ExceptionHandler(Exception.class)注解的方法来处理所有意料之外的异常。