最近我被分配了一个任务:在SpringBoot的Web应用中实现异常处理机制。就像几乎所有SpringBoot项目一样, 有许多不同的方法来实现它。以下是我的研究结果和最终解决方案。
需求
不同需求如下:
#1返回的错误消息必须与框架提供的格式兼容,特别是在JSON中,格式为:
{ <font>"timestamp"</font><font>: 1539797674906, </font><font>"path"</font><font>: </font><font>"/"</font><font>, </font><font>"status"</font><font>: 418, </font><font>"error"</font><font>: </font><font>"I'm a teapot"</font><font>, </font><font>"message"</font><font>: </font><font>"Teapot Mike!"</font><font> } </font>
出于多种原因,这种兼容性很重要。
首先,API使用者始终使用相同的错误格式
其次,仍然可以使用JSR-303 / JSR-348 Bean验证机制,我认为输入验证应该在域本身中进行,尽可能接近领域模型。然而,@NotNull等一些注释字段将让我们拒绝传入的请求因而无需进一步处理。如果发生验证错误,则会在响应中添加一个附加字段 - errors,这是映射到 BindingResult 对象的。
再者,现在有一种趋势是将应用程序代码尽可能地与框架分开。虽然我知道这个目的,但我也意识到应用程序是沉浸在框架中 - 在这种情况下,我发现使用框架机制是合理的。
#2应用程序中抛出的所有异常都应自动转换为相应的HTTP状态代码。
有人可能会想,我是想在应用程序中引入基于异常的通信。当然不是。我希望所有的异常都可以在视图层(@Controller)中解决。
#3所有异常应该从一个基类扩展(DomainException)
#4应该有一个集中的点,可以捕获和处理所有异常。另外,如果可以将这样的异常处理程序透明地注入到应用程序中,那将会很棒。
#5我想在错误响应中添加一个额外的字段 - traceId。在基于微服务的应用程序中,它使调试问题更少。
实现目标
要在基于 Spring Webflux 的应用程序中处理异常,您可以:
该文批判了前面两个点,理由非常饶人,这里不做详细阐述,文章最后推荐第三点:
第三点满足所有要求:
满足#1格式兼容性 - 正如我之前所说,在Spring Framework中没有代表错误响应的类,它只是一个Map。
对于#2和#3,我们有一个可扩展的DomainException - 一切都很好!
#4 DomainExceptionWrapper是一个可注入的单个组件,可以作为工件发布到maven存储库,并作为依赖项添加到其他应用程序。当上下文启动时,它将被自动检测并作为bean注入。它也很容易测试。
#5由于所有(域,运行时,Spring)异常都在一个地方处理,而旧的异常被Map用作返回的对象,因此很容易从中添加或删除字段。