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}) 

HandlerMethod

For access to the controller method that raised the exception.

WebRequestNativeWebRequest

Generic access to request parameters and request and session attributes without direct use of the Servlet API.

jakarta.servlet.ServletRequestjakarta.servlet.ServletResponse

Choose any specific request or response type (for example, ServletRequest or HttpServletRequest or Spring’s MultipartRequest or MultipartHttpServletRequest).

jakarta.servlet.http.HttpSession

Enforces the presence of a session. As a consequence, such an argument is never null.
Note that session access is not thread-safe. Consider setting the RequestMappingHandlerAdapter instance’s synchronizeOnSession flag to true if multiple requests are allowed to access a session concurrently.

java.security.Principal

Currently authenticated user — possibly a specific Principal implementation class if known.

HttpMethod

The HTTP method of the request.

java.util.Locale

The current request locale, determined by the most specific LocaleResolver available — in effect, the configured LocaleResolver or LocaleContextResolver.

java.util.TimeZonejava.time.ZoneId

The time zone associated with the current request, as determined by a LocaleContextResolver.

java.io.OutputStreamjava.io.Writer

For access to the raw response body, as exposed by the Servlet API.

java.util.Maporg.springframework.ui.Modelorg.springframework.ui.ModelMap

For access to the model for an error response. Always empty.

RedirectAttributes

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.

@SessionAttribute

For access to any session attribute, in contrast to model attributes stored in the session as a result of a class-level @SessionAttributes declaration. See @SessionAttribute for more details.

@RequestAttribute

For access to request attributes. See @RequestAttribute for more details.

5  @ExceptionHandler 的响应

Return valueDescription

@ResponseBody

The return value is converted through HttpMessageConverter instances and written to the response. See @ResponseBody.

HttpEntity<B>ResponseEntity<B>

The return value specifies that the full response (including the HTTP headers and the body) be converted through HttpMessageConverter instances and written to the response. See ResponseEntity.

ErrorResponse

To render an RFC 7807 error response with details in the body, see Error Responses

ProblemDetail

To render an RFC 7807 error response with details in the body, see Error Responses

String

A view name to be resolved with ViewResolver implementations and used together with the implicit model — determined through command objects and @ModelAttribute methods. The handler method can also programmatically enrich the model by declaring a Model argument (described earlier).

View

View instance to use for rendering together with the implicit model — determined through command objects and @ModelAttribute methods. The handler method may also programmatically enrich the model by declaring a Model argument (descried earlier).

java.util.Maporg.springframework.ui.Model

Attributes to be added to the implicit model with the view name implicitly determined through a RequestToViewNameTranslator.

@ModelAttribute

An attribute to be added to the model with the view name implicitly determined through a RequestToViewNameTranslator.

Note that @ModelAttribute is optional. See “Any other return value” at the end of this table.

ModelAndView object

The view and model attributes to use and, optionally, a response status.

void

A method with a void return type (or null return value) is considered to have fully handled the response if it also has a ServletResponse an OutputStream argument, or a @ResponseStatus annotation. The same is also true if the controller has made a positive ETag or lastModified timestamp check (see Controllers for details).

If none of the above is true, a void return type can also indicate “no response body” for REST controllers or default view name selection for HTML controllers.

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

 

posted @ 2023-02-20 17:44  zhenjingcool  阅读(19)  评论(0编辑  收藏  举报