springmvc异常处理
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状态码、自定义业务错误码等等。