我正在尝试 Build 一个大型REST服务服务器 . 我们使用的是Spring Boot 1.2.1 Spring 4.1.5和Java 8.我们的控制器正在实现@RestController和标准的@RequestMapping注释 .
我的问题是Spring Boot为控制器异常设置了默认重定向到 /error
. 来自文档:
Spring Boot默认提供/错误映射,以合理的方式处理所有错误,并在servlet容器中注册为“全局”错误页面 .
从使用Node.js编写REST应用程序多年来,对我来说,这对任何事情都是明智的 . 服务 endpoints 生成的任何异常都应在响应中返回 . 我无法理解为什么你发送一个重定向到最有可能是Angular或JQuery SPA消费者的消息,它只是寻找答案而不能或不会对重定向采取任何行动 .
我想要做的是设置一个全局错误处理程序,可以接受任何异常 - 有意地从请求映射方法抛出或由Spring自动生成(如果没有找到请求路径签名的处理程序方法,则为404),并返回标准格式化错误响应(400,500,503,404)到没有任何MVC重定向的客户端 . 具体来说,我们将采用错误,使用UUID将其记录到NoSQL,然后使用JSON正文中日志条目的UUID向客户端返回正确的HTTP错误代码 .
对于如何做到这一点,文档一直含糊不清 . 在我看来,你必须创建自己的ErrorController实现或以某种方式使用ControllerAdvice,但所有的例子我都有帮助 . 其他示例表明您必须列出要处理的每个Exception类型,而不是仅列出"Throwable"并获取所有内容 .
任何人都可以告诉我我错过了什么,或指出我如何做到这一点的正确方向,而不建议Node.js更容易处理的链?
9 回答
使用
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
和@EnableWebMvc @ControllerAdvice
的解决方案适用于Spring Boot 1.3.1,而不适用于1.2.7New answer (2016-04-20)
使用Spring Boot 1.3.1.RELEASE
New Step 1 - 将以下属性添加到application.properties很容易且不那么干扰:
如果使用完整的RESTful应用程序,禁用静态资源的自动映射非常重要,因为如果您使用Spring Boot的默认配置来处理静态资源,那么资源处理程序将处理请求(它最后排序并映射到/ **这意味着它会获取应用程序中任何其他处理程序尚未处理的任何请求),因此调度程序servlet没有机会抛出异常 .
New Answer (2015-12-04)
使用Spring Boot 1.2.7.RELEASE
New Step 1 - 我发现设置"throExceptionIfNoHandlerFound"标志的方式要少得多 . 在应用程序初始化类中将此替换DispatcherServlet替换代码(步骤1):
在这种情况下,我们在现有DispatcherServlet上设置标志,该标志保留Spring Boot框架的任何自动配置 .
我发现还有一件事 - @EnableWebMvc注释对Spring Boot来说是致命的 . 是的,该注释能够捕获所有控制器异常,如下所述,但它也会杀死Spring Boot通常提供的大量有用的自动配置 . 使用Spring Boot时,请极其谨慎地使用该注释 .
Original Answer:
经过大量研究并跟进这里发布的解决方案(感谢帮助!)以及对Spring代码的少量运行时跟踪,我终于找到了一个可以处理所有异常的配置(不是错误,而是继续阅读)包括404s .
Step 1 - 告诉SpringBoot停止在"handler not found"情况下使用MVC . 我们希望Spring抛出异常,而不是返回到客户端,视图重定向到"/error" . 为此,您需要在其中一个配置类中包含一个条目:
这样做的缺点是它取代了默认的调度程序servlet . 这对我们来说还不是问题,没有出现副作用或执行问题 . 如果您出于其他原因要对调度程序servlet执行任何其他操作,则可以执行此操作 .
Step 2 - 现在,当没有找到处理程序时,spring引导将抛出异常,可以使用统一异常处理程序中的任何其他异常处理该异常:
请记住,我认为“@EnableWebMvc”注释在这里很重要 . 似乎如果没有它,这一切都无法奏效 . 就是这样 - 您的Spring启动应用程序现在将捕获上述处理程序类中的所有异常,包括404,您可以随意使用它们 .
最后一点 - 似乎没有办法让它捕获抛出的错误 . 我有一个古怪的想法,使用方面来捕获错误,并将它们变成异常上面的代码然后可以处理,但我还没有时间实际尝试实现它 . 希望这有助于某人 .
任何评论/更正/改进将不胜感激 .
使用Spring Boot 1.4,增加了新的酷类,以便更轻松地处理异常处理,这有助于删除样板代码 .
为异常处理提供了新的
@RestControllerAdvice
,它是@ControllerAdvice
和@ResponseBody
的组合 . 使用此新注释时,可以删除@ExceptionHandler
方法上的@ResponseBody
.即
为了处理404错误,将
@EnableWebMvc
注释和以下内容添加到application.properties就足够了:spring.mvc.throw-exception-if-no-handler-found=true
您可以在这里找到并使用这些来源:
https://github.com/magiccrafter/spring-boot-exception-handling
虽然这是一个较老的问题,但我想就此分享我的想法 . 我希望,对你们中的一些人有所帮助 .
我目前正在构建一个REST API,它使用Spring Boot 1.5.2.RELEASE和Spring Framework 4.3.7.RELEASE . 我使用Java Config方法(而不是XML配置) . 此外,我的项目使用
@RestControllerAdvice
注释的全局异常处理机制(请参阅下文) .我的项目与您的项目具有相同的要求:我希望我的REST API在尝试向不存在的URL发送请求时,在API响应的HTTP响应中返回带有JSON有效负载的
HTTP 404 Not Found
. 在我的例子中,JSON有效负载看起来像这样(明显不同于Spring Boot默认值,顺便说一句 . ):我终于成功了 . 以下是您需要做的主要任务:
如果API客户端调用不存在处理程序方法的URL,请确保抛出
NoHandlerFoundException
(请参阅下面的步骤1) .创建一个自定义错误类(在我的情况下为
ApiError
),其中包含应返回给API客户端的所有数据(请参阅步骤2) .创建一个异常处理程序,它对
NoHandlerFoundException
做出反应,并向API客户端返回正确的错误消息(请参阅步骤3) .为它编写测试并确保它有效(参见步骤4) .
好的,现在详细说明:
Step 1: Configure application.properties
我必须将以下两个配置设置添加到项目的
application.properties
文件中:这样可以确保在客户端尝试访问不存在能够处理请求的控制器方法的URL的情况下抛出
NoHandlerFoundException
.Step 2: Create a Class for API Errors
我在Eugen Paraschiv的博客上创建了类似于this article中建议的类 . 此类表示API错误 . 如果出现错误,此信息将发送到HTTP响应正文中的客户端 .
Step 3: Create / Configure a Global Exception Handler
我使用以下类来处理异常(为简单起见,我删除了import语句,记录代码和其他一些不相关的代码片段):
Step 4: Write a test
我想确保,即使出现故障,API也始终向调用客户端返回正确的错误消息 . 因此,我写了一个这样的测试:
@ActiveProfiles("dev")
注释可以保留 . 我只在使用不同的配置文件时使用它 .RegexMatcher
是一个自定义Hamcrest matcher我用来更好地处理时间戳字段 . 这是代码(我发现它here):Some further notes from my side:
在StackOverflow上的许多其他帖子中,人们建议设置
@EnableWebMvc
注释 . 在我的情况下,这不是必要的 .这种方法适用于MockMvc(参见上面的测试) .
默认情况下,Spring Boot为json提供错误详细信息 .
它也适用于所有类型的请求映射错误 . 查看这篇文章http://www.jayway.com/2014/10/19/spring-boot-error-responses/
如果要创建将其登录到NoSQL . 您可以在其中创建@ControllerAdvice,然后重新抛出异常 . 文档中有例子https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
@RestControllerAdvice是Spring Framework 4.3的一个新功能,它通过一个跨领域的关注解决方案来处理RestfulApi的异常:
我认为
ResponseEntityExceptionHandler
符合您的要求 . HTTP 400的示例代码:你可以查看post
这段代码怎么样?我使用回退请求映射来捕获404错误 .
对于REST控制器,我建议使用
Zalando Problem Spring Web
.https://github.com/zalando/problem-spring-web
如果Spring Boot旨在嵌入一些自动配置,那么这个库可以为异常处理提供更多功能 . 您只需要添加依赖项:
然后为您的例外定义一个或多个建议特征(或使用默认提供的特征)
然后,您可以将异常处理的控制器建议定义为: