正确使用Spring Boot的ErrorController和Spring的ResponseEntityExceptionHandler [英] Using Spring Boot's ErrorController and Spring's ResponseEntityExceptionHandler correctly

查看:130
本文介绍了正确使用Spring Boot的ErrorController和Spring的ResponseEntityExceptionHandler的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Spring Boot中创建控制器以自定义方式处理所有错误/异常时,包括自定义

When creating a controller in Spring Boot to handle all errors/exceptions in a custom way, including custom exceptions, which technique should be preferred?


  1. 控制器应该实现Spring Boot的吗? ErrorController

控制器应该扩展Spring的 ResponseEntityExceptionHandler 吗?

Should the controller extend Spring's ResponseEntityExceptionHandler?

都是:一个控制器实现并扩展两个类,包括它们的两个功能吗?

Both: a single controller implementing and extending both classes including both of their functionality?

都:两个单独的控制器,一个实现 ErrorController ,另一个扩展 ResponseEntityExceptionHandler

Both: two separate controllers, one implementing ErrorController, the other extending ResponseEntityExceptionHandler?



目标



这篇文章的原因是在Spring中找到一种异常处理方法使用以下属性的 all 进行引导:


  • 所有 Throwable
  • 在捕获 Throwable 的情况下,我们不要不想向客户端公开任何堆栈跟踪或其他实现细节(除非以这种方式明确编码)。

  • 它应该有可能按其类分别处理所有发生的 Throwable 。对于任何其他未指定的类型,可以指定默认响应。 (我肯定知道, 可以通过 @ExceptionHandler 来实现。但是 ErrorController 吗? )

  • 代码应尽可能简洁明了,没有丑陋的解决方法或UB来实现此目标。

  • All Throwables occurring in controllers/filters/interceptors during the handling of a request should be caught.
  • In the case of catching a Throwable, we do not want to expose any of the stack trace or other implementation details to the client ever (unless explicitly coded that way).
  • It should be possible to handle all occurred Throwables separately by their class. For any other non-specified type, a default response can be specified. (I know for sure, that this is possible with @ExceptionHandler. But ErrorController?)
  • The code should be as clean and explicit as possible with no ugly work-arounds or UB to achieve this goal.

我注意到两个控制器(请参见上面的1和2)可能都包含返回 ResponseEntity的方法对象,从而处理发生的异常并将响应返回给客户端。

I noticed that both the controllers (see 1 and 2 above) may contain methods returning a ResponseEntity object, thus handling the occurred exception and returning a response to the client. So they could in theory produce the same result?

那里有几本关于技巧1和2的使用的教程。但是我发现没有关于这两种选择的文章,比较它们或将它们一起使用,会引发其他一些问题:

There are several tutorials out there on the use of techniques 1 and 2. But I have found no articles considering both options, comparing them or using them together, which raises several additional questions:


  1. 甚至应该一起考虑吗?

  1. Should they even be considered together?

这两种提议的技术之间的主要区别是什么?有什么相似之处?

What are the main differences between these two proposed techniques? What are the similarities?

一个是另一个的更强大的版本吗?

Is one a more powerful version of the other? Is there something one can do that the other can't and vice versa?

它们可以一起使用吗?

如果将它们一起使用,将如何处理异常?它是通过两个处理程序还是通过一个处理程序?对于后者,是哪个?

If they are used together, how would an exception be handled? Does it go through both handlers or just one? In the case of the latter, which one?

如果将它们一起使用,并且在控制器内 中引发异常(一个或另一个)在异常处理期间,该异常将如何处理?是否发送到另一个控制器?从理论上讲,异常可以在控制器之间开始反弹吗?还是会创建其他类型的不可恢复循环?

If they are used together, and an exception is thrown inside the controller (one or the other) during exception handling, how would that exception be handled? Is it sent to the other controller? Could exceptions theoretically start bouncing between controllers or create some other kind of non-recovering loop?

是否存在关于Spring Boot如何使用Spring的 ResponseEntityExceptionHandler 内部还是期望它在Spring Boot应用程序中使用?

Is there any trusted/official documentation on how Spring Boot uses Spring's ResponseEntityExceptionHandler internally or how it expects it to be used in Spring Boot applications?

如果 ResponseEntityExceptionHandler 就足够了,那么为什么 ErrorController 存在呢?

If ResponseEntityExceptionHandler alone is already enough, then why does ErrorController exist?

在查看Spring的 ResponseEntityExceptionHandler @ExceptionHandler 批注时,它似乎在分别处理不同类型的异常和使用更简洁的代码方面更强大。但是,因为Spring Boot是基于Spring构建的,所以这意味着:

When looking at the Spring's ResponseEntityExceptionHandler together with the @ExceptionHandler annotation, it seems to be more powerful in handling different types of exceptions separately and using cleaner code. But because Spring Boot is built on top of Spring, does this mean:


  • 使用Spring Boot时,我们应该实现 ErrorController 而不是扩展 ResponseEntityExceptionHandler

  • 可以 ErrorController ResponseEntityExceptionHandler 能做的一切,包括分别处理不同类型的异常吗?

  • When using Spring Boot, we should implement ErrorController instead of extending ResponseEntityExceptionHandler?
  • Can ErrorController do everything ResponseEntityExceptionHandler can, including handling different types of exceptions separately?

编辑:相关: Spring @ControllerAdvice与ErrorController

推荐答案

Spring Boot应用程序具有用于错误处理的默认配置- ErrorMvcAutoConfiguration

Spring Boot application has a default configuration for error handling - ErrorMvcAutoConfiguration.

如果没有,它的基本作用是什么提供的其他配置:

What it basically does, if no additional configuration provided:


  • 它创建默认的全局错误控制器- BasicErrorController

  • 它会创建默认的错误静态视图 Whitelabel错误页面。

BasicErrorController 默认情况下连接到'/ error'。如果应用程序中没有自定义的错误视图,则在任何控制器抛出异常的情况下,用户将进入/ error whitelabel页面,该页面由BasicErrorController填充信息。

BasicErrorController is wired to '/error' by default. If there is no customized 'error' view in the application, in case of an exception thrown from any controller, the user lands to /error whitelabel page, filled with information by BasicErrorController.

如果应用程序具有实现 ErrorController 的控制器,它将替换 BasicErrorController

If application has a controller implementing ErrorController it replaces BasicErrorController.

如果在错误处理控制器中发生任何异常,它将通过Spring异常过滤器(请参阅下面的更多详细信息),最后,如果没有发现任何异常,则底层应用程序将处理该异常容器,例如雄猫基础容器将处理该异常并根据其实现显示一些错误页面/消息。

If any exception occurs in error handling controller, it will go through Spring exception filter (see more details down below) and finally if nothing is found this exception will be handled by the underlying application container, e.g. Tomcat. The underlying container will handle the exception and show some error page/message depending on its implementation.

BasicErrorController <中有一条有趣的信息/ code> javadoc


基本的全局错误控制器,呈现ErrorAttributes。可以使用Spring MVC抽象(例如 @ExceptionHandler )或添加servlet服务器错误页面来处理更具体的错误。

Basic global error Controller, rendering ErrorAttributes. More specific errors can be handled either using Spring MVC abstractions (e.g. @ExceptionHandler) or by adding servlet server error pages.

BasicErrorController ErrorController 实现是全局错误处理程序。它可以与@ExceptionHandler结合使用。

BasicErrorController or ErrorController implementation is a global error handler. It can be used in conjunction with @ExceptionHandler.

在这里,我们来到 ResponseEntityExceptionHandler


@ControllerAdvice类的便捷基类,希望通过@ExceptionHandler方法在所有@RequestMapping方法中提供集中式异常处理。
这个基类提供了一个@ExceptionHandler方法,用于处理内部Spring MVC异常。

A convenient base class for @ControllerAdvice classes that wish to provide centralized exception handling across all @RequestMapping methods through @ExceptionHandler methods. This base class provides an @ExceptionHandler method for handling internal Spring MVC exceptions.

换句话说,这意味着 ResponseEntityExceptionHandler 只是一个便利类,它已经包含Spring MVC异常处理。我们可以将其用作自定义类的基类,以处理控制器的异常。为了使自定义类起作用,必须使用 @ControllerAdvice 进行注释。

In other words, that means that ResponseEntityExceptionHandler is just a convenience class, which already contains Spring MVC exception handling. And we can use it as a base class for our custom class to handle controllers' exceptions. For our custom class to work, it must be annotated with @ControllerAdvice.

使用<$ c $进行注释的类c> @ControllerAdvice 可以与全局错误处理程序( BasicErrorController ErrorController 实现)。如果我们的 @ControllerAdvice 带注释的类(不能扩展 ResponseEntityExceptionHandler )不能处理某些异常,则该异常

Classes annotated with @ControllerAdvice can be used at the same time as the global error handler (BasicErrorController or ErrorController implementation). If our @ControllerAdvice annotated class (which can/or not extend ResponseEntityExceptionHandler) doesn't handle some exception, the exception goes to the global error handler.

到目前为止,我们已经研究了 ErrorHandler 控制器以及任何带有<$ c $注释的内容c> @ControllerAdvice 。但这要复杂得多。
我在这个问题中发现了一个非常有价值的见解-设置多个@ControllerAdvice的优先级@ExceptionHandlers

So far we looked at ErrorHandler controller and anything annotated with @ControllerAdvice. But it is much more complicated. I found a really valuable insight in the question - Setting Precedence of Multiple @ControllerAdvice @ExceptionHandlers.

编辑:

为简单起见:


  1. 第一个Spring在@ControllerAdvice类中搜索异常处理程序(用@ExceptionHandler注释的方法)。参见 ExceptionHandlerExceptionResolver

  2. 然后,它检查抛出的异常是用@ResponseStatus注释还是从ResponseStatusException派生。参见 ResponseStatusExceptionResolver

  3. 然后它通过Spring MVC异常的默认处理程序。参见 DefaultHandlerExceptionResolver

  4. 最后,如果未找到任何内容,则将控件转发到错误页面视图,并在其后放置全局错误处理程序。如果异常来自错误处理程序本身,则不执行此步骤。

  5. 如果未找到错误视图(例如,禁用了全局错误处理程序)或跳过了步骤4,则异常为由容器处理。

  1. First Spring searches for an exception handler (a method annotated with @ExceptionHandler) within @ControllerAdvice classes. See ExceptionHandlerExceptionResolver.
  2. Then it checks if the thrown exception is annotated with @ResponseStatus or derives from ResponseStatusException. See ResponseStatusExceptionResolver.
  3. Then it goes through Spring MVC exceptions' default handlers. See DefaultHandlerExceptionResolver.
  4. And at the end if nothing is found, the control is forwarded to the error page view with the global error handler behind it. This step is not executed if the exception comes from the error handler itself.
  5. If no error view is found (e.g. global error handler is disabled) or step 4 is skipped, then the exception is handled by the container.

这篇关于正确使用Spring Boot的ErrorController和Spring的ResponseEntityExceptionHandler的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆