ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java-正确使用Spring Boot的ErrorController和Spring的ResponseEntityExceptionHandler

2019-11-08 06:28:46  阅读:610  来源: 互联网

标签:spring-boot error-handling exception spring java


问题

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

>控制器应该实现Spring Boot的ErrorController吗?
>控制器是否应该扩展Spring的ResponseEntityExceptionHandler?
>两者:实现和扩展两个类(包括它们的功能)的单个控制器?
>两者:两个单独的控制器,一个实现ErrorController,另一个扩展ResponseEntityExceptionHandler?

目标

这篇文章的原因是在Spring Boot中找到一种具有以下所有属性的异常处理方法:

>应该捕获在处理请求期间在控制器/过滤器/拦截器中发生的所有Throwable.
>在捕获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

解决方法:

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

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

>它创建默认的全局错误控制器-BasicErrorController
>它会创建默认的“错误”静态视图“ Whitelabel错误页面”.

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

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

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

BasicErrorController javadoc中有一条有趣的信息:

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结合使用.

这里我们来ResponseEntityExceptionHandler

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对其进行注释.

用@ControllerAdvice注释的类可以与全局错误处理程序(BasicErrorController或ErrorController实现)同时使用.如果我们的@ControllerAdvice带注释的类(不能/不能扩展ResponseEntityExceptionHandler)不处理某些异常,则该异常将进入全局错误处理程序.

到目前为止,我们已经研究了ErrorHandler控制器以及所有带有@ControllerAdvice注释的内容.但这要复杂得多.
我在这个问题上找到了非常有价值的见解-Setting Precedence of Multiple @ControllerAdvice @ExceptionHandlers.

编辑:

为简单起见:

> First Spring在@ControllerAdvice类中搜索异常处理程序(用@ExceptionHandler注释的方法).参见ExceptionHandlerExceptionResolver.
>然后,它检查抛出的异常是用@ResponseStatus注释还是从ResponseStatusException派生.参见ResponseStatusExceptionResolver.
>然后遍历Spring MVC异常的默认处理程序.参见DefaultHandlerExceptionResolver.
>最后,如果未找到任何内容,则将控件转发到错误页面视图,并在其后面放置全局错误处理程序.如果异常来自错误处理程序本身,则不会执行此步骤.
>如果未找到错误视图(例如,禁用了全局错误处理程序)或跳过了步骤4,则该异常将由容器处理.

标签:spring-boot,error-handling,exception,spring,java
来源: https://codeday.me/bug/20191108/2006214.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有