当前位置: 首页 > 知识库问答 >
问题:

正确使用spring boot的ErrorController和spring的ResponseEntityExceptionHandler

魏臻
2023-03-14

在spring boot创建控制器以自定义方式处理所有错误/异常(包括自定义异常)时,应该首选哪种技术?

>

  • 控制器是否应该实现spring boot的errorcontroller

    控制器是否应该扩展spring的ResponseEntityExceptionHandler

    两者:一个html" target="_blank">控制器实现和扩展两个类,包括它们的功能?

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

    写这篇文章的原因是要找到一种在spring boot中处理异常的方法,它具有以下所有属性:

    • 应捕获处理请求期间控制器/筛选器/拦截器中出现的所有可抛出
    • 在捕获throwable的情况下,我们不希望向客户端公开任何堆栈跟踪或其他实现细节(除非以这种方式显式编码)。
    • 应该可以按类分别处理所有发生的throwable。对于任何其他未指定的类型,都可以指定默认响应。(我肯定地知道,使用@exceptionhandler可以做到这一点。但是errorcontroller?)
    • 代码应该尽可能清晰明确,没有难看的工作边界或UB来实现此目标。

    我注意到这两个控制器(参见上面的1和2)都可能包含返回responseEntity对象的方法,从而处理发生的异常并向客户端返回响应。所以理论上他们也能产生同样的结果?

    关于技术1和2的使用,有几个教程。但我没有发现任何文章考虑到这两种选择,比较它们或将它们一起使用,这又提出了几个问题:

    >

  • 它们是否应该一起考虑?

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

    一个是另一个更强大的版本吗?有没有什么事情一个人能做,另一个人做不到,反之亦然?

    它们可以一起使用吗?是否有需要这样做的情况?

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

    如果它们一起使用,并且在异常处理期间在控制器内部抛出异常(一个或另一个),该异常将如何处理?发送到另一个控制器了吗?从理论上讲,异常会不会开始在控制器之间反弹,或者产生某种其他类型的非恢复循环?

    关于spring boot如何在内部使用spring的ResponseEntityExceptionHandler或如何期望其在spring boot应用程序中使用,是否有可信的/官方文档?

    如果仅有ResponseEntityExceptionHandler就已经足够了,那么为什么还存在ErrorController呢?

    当将spring的ResponseEntityExceptionHandler@ExceptionHandler注释一起查看时,它似乎在单独处理不同类型的异常和使用更干净的代码方面更加强大。但因为spring boot建在spring之上,这是否意味着:

    • 使用spring boot时,应实现ErrorController而不是扩展ResponseEntityExceptionHandler
    • ErrorController是否可以执行ResponseEntityExceptionHandler可以执行的所有操作,包括单独处理不同类型的异常?

    编辑:相关:spring@ControllerAdvice vs ErrorController

  • 共有1个答案

    夏季萌
    2023-03-14

    spring boot应用程序有一个错误处理的默认配置--ErrorMVCautoConfiguration。

    如果没有提供其他配置,它的基本功能是:

    • 它创建默认全局错误控制器-BasicErrorController
    • 它将创建默认的“错误”静态视图“白标签错误页”。

    BasicErrorController默认情况下连接到“/error”。如果应用程序中没有自定义的“error”视图,在任何控制器抛出异常的情况下,用户将登陆/error白标签页面,该页面由BasicErrorController填充信息。

    如果应用程序有一个实现errorcontroller的控制器,它将替换basicerrorcontroller

    如果在错误处理控制器中出现任何异常,它将通过spring异常过滤器(参见下面的更多细节),最后,如果没有发现任何异常,则该异常将由底层应用程序容器(例如Tomcat)处理。底层容器将处理异常,并根据其实现显示一些错误页面/消息。

    BasicErrorControllerJavadoc中有一条有趣的信息:

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

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

    这里是ResponseEntityExceptionHandler

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

    换句话说,那意味着ResponseEntityExceptionHandler只是一个方便类,它已经包含了spring MVC异常处理。并且我们可以使用它作为自定义类的基类来处理控制器的异常。为了使我们的自定义类工作,必须使用@controlleradvice对其进行注释。

    @ControllerAdvice注释的类可以同时用作全局错误处理程序(BasicErrorControllerErrorController实现)。如果我们的@ControllerAdvice注释类(可以/或不扩展ResponseEntityExceptionHandler)不处理某个异常,则该异常将转到全局错误处理程序。

    到目前为止,我们查看了errorhandler控制器和任何带有@controlleradvice注释的东西。但要复杂得多。我在多个@ControllerAdvice@ExceptionHandlers的问题设置优先级中发现了一个非常有价值的见解。

    编辑:

    为了简单起见:

    1. 首先,spring在@ControllerAdvice类中搜索一个异常处理程序(一个用@ExceptionHandler注释的方法)。请参阅ExceptionHandlerExceptionResolver。
    2. 然后检查抛出的异常是用@ResponseStatus注释的还是从ResponseStatusException派生的。请参阅ResponseStatusExceptionResolver。
    3. 然后通过spring MVC异常的默认处理程序。请参阅DefaultHandlerExceptionResolver。
    4. 并且在结束时,如果未找到任何内容,则将控件转发到error page视图,全局错误处理程序位于其后面。如果异常来自错误处理程序本身,则不执行此步骤。
    5. 如果未找到错误视图(例如禁用全局错误处理程序)或跳过步骤4,则该异常将由容器处理。
     类似资料:
    • 基本上,我正在使用spring boot和thymeleaf创建一个餐厅餐饮网站(只是一个课程的练习),厨师提供自助餐,每个自助餐由不同的菜肴和不同的配料组成(对不起,我的英语)。 我的问题是:我应该使用来指示厨师制作的自助餐吗? 或者我应该直接使用(“/自助餐”)?因为对于配料的控制器,我最终会使用<代码>(“/厨师/{id}/自助餐/{id}/盘子{id}/配料”) ,它看起来很奇怪,但我认为

    • 如何使JavaFX WebView正确使用IPv6?或者,如果不可能的话,在Java上正确使用IPv6的另一种web浏览器是什么? 编辑:当完全从我的计算机禁用IPv4时,WebView拒绝完全加载任何内容,尽管它似乎有能力使用IPv6。

    • 我读过几本教程,也读过@mattt的自述,但我还是搞不懂几件事。 > 在实际API中的正确用法是什么?看起来,如果我将通过为所有API实现 协议来创建一个路由器,那么它将几乎不可读。是否应该为每个endpoint创建一个路由器? 第二个问题很可能是由于缺乏使用Swift语言的经验引起的。我不明白为什么要用 来构建路由器?为什么我们不将类与静态方法一起使用?这里有一个例子(来自Alamofire's

    • 问题内容: 我正在阅读有关PyQt5的一些文档,以提出一种简单的信号插槽机制。由于设计方面的考虑,我停了下来。 考虑以下代码: 为了跟踪对滑块所做的更改,我仅打印并记录所做的更改。我对代码不满意的是,我需要调用三次插槽以将相同的信息发送到3个不同的插槽。 是否可以创建自己的将整数发送到单个插槽的函数。插槽功能又会发出需要进行的更改吗? 也许我不完全了解它的目的,因为在PyQt Signal-Slo

    • 我用PHPass散列密码已经很久了。我承认仍然有一些我不完全理解(或忽略)的东西来正确地散列密码,所以今天我查看了所有我能找到的关于它的信息。 回顾PHPass文档,我已经进入了这个: 除了实际的哈希之外,phpass 在对新密码或密码进行哈希处理时会透明地生成随机 salt,并将哈希类型、salt 和密码拉伸迭代计数编码到它返回的“hash 编码字符串”中。当phpass根据存储的哈希对密码或密

    • 使用Spring Boot 2.0.0.rc2。 和junit-platform-surefire-provider配置在maven-surefire-pluginV2.19.1中 我似乎找不出合适的注释来让我的测试类读取src/Test/resources/application-test.yml中的配置。 我读过https://junit.org/junit5/docs/current/use