SpringMVC 教程 - Exception,Controller Advice

1,708 阅读3分钟
原文链接: www.codemore.top

@Controller@ControllerAdvice类可以有多个@ExceptionHandler修饰的方法来处理controller抛出的异常样。例如:

@Controller
public class SimpleController {

    // ...

    @ExceptionHandler
    public ResponseEntity<String> handle(IOException ex) {
        // ...
    }

}

注解可以列出匹配的异常,或者像上面的代码一样,在方法中列出异常。当有多个异常匹配的时候,ExceptionDepthComparator可以根据异常的深度来匹配处理异常的函数。 有多个@ControllerAdvice的时候,需要根据声明的异常匹配的@ControllerAdvice来进行优先级排序。因为异常匹配的时候高优先级的@ControllerAdvice比低优先级的更鲜匹配。

函数参数
函数参数 解释
异常类型 访问抛出的异常
HandlerMethod 访问抛出异常的方法
WebRequest,NativeWebRequest 访问请求参数,session等
ServletRequest,ServletResponse 可以是指定的请求和响应类型例如ServletRequest,HttpServletRequest,也可以是Spring的MultipartRequest,MultipartHttpServletRequest
HttpSession 参数永不为null,访问session非线程安全,如果多个请求访问一个session,需要设置RequestMappingHandlerAdapter的synchronizeOnSession为true。
Principal 当前授权用户。
HttpMethod 请求的HTTP方法
Locale 当前请求的区域,由LocaleResolver解析
TimeZone,ZoneId LocaleContextResolver解析的当前请求的时区
OutputStream,Writer 访问由Servlet API 暴露的响应体
Map,Model,ModelMap 访问会在渲染模板时使用的变量。
RedirectAttributes 重定向时使用的属性
@SessionAttributes 在不同的请求中存储session
@RequestAttribute 访问请求的属性。
返回值
返回值类型 解释
@ResponseBody 返回值由HttpMessageConverters转换,直接写到响应体
HttpEntity<B>, ResponseEntity<B> 返回值包括,http header和body
String ViewResolver解析出具体的模板渲染。
View 返回具体的视图
Map,Model model包含的属性,视图由RequestToViewNameTranslator解析
@ModelAttribute 返回添加到Model的属性,视图由RequestToViewNameTranslator解析.
ModelAndView 返回具体视图和添加的model
void 返回void,则Spring MVC会认为Controller内部已经处理好响应内容了。
其他类型 如果不返回以上类型,默认当作model属性处理。
REST API 异常

REST 服务一般需要将错误的细节放到响应体中。Spring Framework默认并不支持这样处理,因为这属于应用层需要做的事情。然而@RestController可以使用@ExceptionHandler方法通过返回ResponseEntity来包含错误信息。这些方法同样可以放到@ControllerAdvice中。 如果应用需要实现全局的异常处理同时将错误信息放到响应体中,可以实现ResponseEntityExceptionHandler来处理Spring MVC的引发的异常,将错误写入响应体中。步骤如下: 1. 继承ResponseEntityExceptionHandler,重写响应方法。 2. 使用@ControllerAdvice修饰。 3. 注册为Spring bean

Controller Advice

一般来讲@ExceptionHandler,@InitBinder,@ModelAttribute修饰的方法都是直接放在其声明使用的@Controller中的。如果要声明跨controller的全局函数,就需要在@ControllerAdvice或者@RestControllerAdvice中声明。 @ControllerAdvice@Component标记,所以可以自动的注册为Spring的bean。@RestControllerAdvice@ControllerAdvice@ResponseBody的组合,意味着@ExceptionHandler修饰的方法可以直接通过类型转换将返回值写入到响应体中。 启动后,@RequestMapping,@ExceptionHandler的函数会检测类型为@ControllerAdvice的bean,然后动态运行他们的方法。@ControllerAdvice的全局的@ExceptionHandler的优先级低于在本地@ExceptionHandler的优先级,而@ModelAttribute@InitBinder则恰好想法,他们会在本地的方法执行之前执行。 默认情况下@ControllerAdvice应用与所有的请求,例如所有的controller,但是也可以通过@ControllerAdvice的属性来缩小这个范围,例如:

// Target all Controllers annotated with @RestController
@ControllerAdvice(annotations = RestController.class)
public class ExampleAdvice1 {}

// Target all Controllers within specific packages
@ControllerAdvice("org.example.controllers")
public class ExampleAdvice2 {}

// Target all Controllers assignable to specific classes
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class ExampleAdvice3 {}

由于上述选择器是在运行时确定的,所以可能会有一些性能损失。