1 DispatcherServlet的handlerExceptionResolvers
在DispatcherServlet初始化过程中,执行如下初始化方法
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
其中有一步是初始化异常处理器 initHandlerExceptionResolvers(context);
private void initHandlerExceptionResolvers(ApplicationContext context) {
this.handlerExceptionResolvers = null;
if (this.detectAllHandlerExceptionResolvers) {
// 在上下文中查找所有HandlerExceptionResolvers类型的bean.
Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values());
}
else {
HandlerExceptionResolver her = context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);
this.handlerExceptionResolvers = Collections.singletonList(her);
}
// 如果上一步中没有获取到异常处理器,则使用默认的异常处理器
if (this.handlerExceptionResolvers == null) {
this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);
}
}
默认情况下,detectAllHandlerExceptionResolvers为true,此时会初始化三个HandlerExceptionResolver:
ExceptionHandlerExceptionResolver:使用用户加了@ExceptionHandler注解的方法来处理异常。ResponseStatusExceptionHandler:如果异常类型是ResponseStatusException,则根据异常中的status和reason,利用HttpServletResponse.sendError来返回异常信息。DefaultHandlerExceptionResolver:当前两个解析器没有成功处理,则该处理器会处理一些指定的异常类型,例如HttpRequestMethodNotSupportedException、HttpMediaTypeNotSupportedException、HttpMediaTypeNotAcceptableException等等;通过HttpServletResponse.sendError来返回异常信息。
我们可以通过实现 HandlerExceptionResolver 接口自定义异常处理器
2 @Controller类中使用@ExceptionHandler
该方法就会处理其所在controller类抛出的异常
3 @ControllerAdvice类中使用@ExceptionHandler注解
这样,Controller中抛出的所有异常都会被处理到。
4 官网给出的 @ExceptionHandler 参数
参数 | 描述 |
---|---|
Exception type | 设置需要处理的异常类型.例子: @ExceptionHandler({FileSystemException.class, RemoteException.class}) |
| For access to the controller method that raised the exception. |
| Generic access to request parameters and request and session attributes without direct use of the Servlet API. |
| Choose any specific request or response type (for example, |
| Enforces the presence of a session. As a consequence, such an argument is never |
| Currently authenticated user — possibly a specific |
| The HTTP method of the request. |
| The current request locale, determined by the most specific |
| The time zone associated with the current request, as determined by a |
| For access to the raw response body, as exposed by the Servlet API. |
| For access to the model for an error response. Always empty. |
| Specify attributes to use in case of a redirect — (that is to be appended to the query string) and flash attributes to be stored temporarily until the request after the redirect. See Redirect Attributes and Flash Attributes. |
| For access to any session attribute, in contrast to model attributes stored in the session as a result of a class-level |
| For access to request attributes. See |
5 @ExceptionHandler 的响应
Return value | Description |
---|---|
| The return value is converted through |
| The return value specifies that the full response (including the HTTP headers and the body) be converted through |
| To render an RFC 7807 error response with details in the body, see Error Responses |
| To render an RFC 7807 error response with details in the body, see Error Responses |
| A view name to be resolved with |
| A |
| Attributes to be added to the implicit model with the view name implicitly determined through a |
| An attribute to be added to the model with the view name implicitly determined through a Note that |
| The view and model attributes to use and, optionally, a response status. |
| A method with a If none of the above is true, a |
Any other return value | If a return value is not matched to any of the above and is not a simple type (as determined by BeanUtils#isSimpleProperty), by default, it is treated as a model attribute to be added to the model. If it is a simple type, it remains unresolved. |
因此,我们可以根据不同的异常,返回不通的响应,比如http状态码、自定义业务错误码等等。