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

spring boot REST服务异常处理

邹誉
2023-03-14

我正在尝试建立一个大型的REST服务服务器。我们使用的是spring boot 1.2.1 spring 4.1.5和Java 8。我们的控制器实现了@RestController和标准的@RequestMapping注释。

我的问题是,spring boot将控制器异常设置为/error的默认重定向。从文档中:

默认情况下,spring boot提供了一个/error映射,它以一种合理的方式处理所有错误,并且在servlet容器中注册为一个“全局”错误页面。

多年来用Node.js编写REST应用程序,对我来说,这一点都不明智。服务endpoint生成的任何异常都应在响应中返回。我不明白为什么您要将重定向发送给Angular或JQuery SPA消费者,而这些消费者只是在寻找答案,不能或不会对重定向采取任何行动。

我想要做的是建立一个全局错误处理程序,它可以接受任何异常--从请求映射方法有目的地抛出或由spring自动生成(如果没有为请求路径签名找到处理程序方法,则为404),并向客户机返回一个标准格式化的错误响应(400,500,503,404)而不进行任何MVC重定向。具体地说,我们将接受错误,用一个UUID将其记录到NoSQL,然后用JSON主体中日志条目的UUID将正确的HTTP错误代码返回给客户机。

文件对如何做到这一点含糊其辞。在我看来,您必须要么创建自己的ErrorController实现,要么以某种方式使用ControllerAdvise,但我看到的所有示例仍然包括将响应转发到某种错误映射,这没有帮助。其他示例建议您必须列出您想要处理的每个异常类型,而不是仅仅列出“throwable”并获取所有内容。

有谁能告诉我我错过了什么,或者给我指明正确的方向,告诉我如何做到这一点,而不是暗示Node.js更容易处理吗?

共有2个答案

陆敏学
2023-03-14

在spring boot 1.4+中,添加了更轻松的异常处理的新的酷类,这有助于删除样板代码。

为异常处理提供了一个新的@RestControllerAdvice,它是@ControllerAdvice@ResponseBody的组合。使用此新批注时,可以删除@exceptionhandler方法上的@responsebody

即。

@RestControllerAdvice
public class GlobalControllerExceptionHandler {

    @ExceptionHandler(value = { Exception.class })
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ApiErrorResponse unknownException(Exception ex, WebRequest req) {
        return new ApiErrorResponse(...);
    }
}

要处理404错误,在Application.Properties中添加@enablewebmvc注释和以下内容就足够了:
spring.mvc.throw-exception-if-no-handler-found=true

您可以在这里找到并使用源代码:
https://github.com/magiccrafter/spring-boot-exception-handling

端木安国
2023-03-14

新答案(2016-04-20)

使用spring boot 1.3.1版本

新步骤1-将以下属性添加到应用程序中既简单又不太具有侵扰性。属性:

spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

比修改现有的DispatcherServlet实例容易得多(如下所示)!-乔‘

如果使用完整的RESTful应用程序,禁用静态资源的自动映射是非常重要的,因为如果您使用spring boot的默认配置来处理静态资源,那么资源处理程序将处理请求(它是最后排序的,并映射到/**,这意味着它将接收应用程序中任何其他处理程序尚未处理的任何请求),因此调度器servlet没有机会抛出异常。

新答案(2015-12-04)

使用spring boot 1.2.7版本

新的步骤1-我找到了一种不那么侵入性的设置“ThroExceptionIfnoHandlerFound”标志的方法。在应用程序初始化类中将下面的DispatcherServlet替换代码(步骤1)替换为:

@ComponentScan()
@EnableAutoConfiguration
public class MyApplication extends SpringBootServletInitializer {
    private static Logger LOG = LoggerFactory.getLogger(MyApplication.class);
    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(MyApplication.class, args);
        DispatcherServlet dispatcherServlet = (DispatcherServlet)ctx.getBean("dispatcherServlet");
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
    }

在本例中,我们在现有的DispatcherServlet上设置标志,它保留了spring boot框架的任何自动配置。

我还发现了一件事--@enableWebMVC注释对spring boot来说是致命的。是的,这个注释使我们能够捕获所有的控制器异常(如下所述),但它也扼杀了spring boot通常提供的许多有用的自动配置。当你使用spring boot时,要非常小心地使用那个注释。

原答案:

经过更多的研究和后续的解决方案张贴在这里(感谢帮助!)和大量的运行时跟踪到spring代码中,我终于找到了一个配置,它将处理包括404S在内的所有异常(不是错误,而是继续读取)。

步骤1-告诉springboot停止使用MVC“处理程序找不到”的情况。我们希望spring抛出一个异常,而不是向客户端返回一个重定向到“/error”的视图。为此,您需要在配置类中有一个条目:

// NEW CODE ABOVE REPLACES THIS! (2015-12-04)
@Configuration
public class MyAppConfig {
    @Bean  // Magic entry 
    public DispatcherServlet dispatcherServlet() {
        DispatcherServlet ds = new DispatcherServlet();
        ds.setThrowExceptionIfNoHandlerFound(true);
        return ds;
    }
}

它的缺点是替换了默认的dispatcher servlet。这还不是我们的问题,没有副作用或执行问题显示。如果出于其他原因要对dispatcher servlet执行任何其他操作,那么这里就是执行这些操作的地方。

步骤2-现在spring boot将在未找到处理程序时抛出异常,该异常可以在统一的异常处理程序中与任何其他异常一起处理:

@EnableWebMvc
@ControllerAdvice
public class ServiceExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(Throwable.class)
    @ResponseBody
    ResponseEntity<Object> handleControllerException(HttpServletRequest req, Throwable ex) {
        ErrorResponse errorResponse = new ErrorResponse(ex);
        if(ex instanceof ServiceException) {
            errorResponse.setDetails(((ServiceException)ex).getDetails());
        }
        if(ex instanceof ServiceHttpException) {
            return new ResponseEntity<Object>(errorResponse,((ServiceHttpException)ex).getStatus());
        } else {
            return new ResponseEntity<Object>(errorResponse,HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @Override
    protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        Map<String,String> responseBody = new HashMap<>();
        responseBody.put("path",request.getContextPath());
        responseBody.put("message","The URL you have reached is not in service at this time (404).");
        return new ResponseEntity<Object>(responseBody,HttpStatus.NOT_FOUND);
    }
    ...
}

请记住,我认为“@enablewebmvc”注释在这里很重要。似乎没有它这些都行不通。就是这样--你的spring boot应用程序现在将捕获上面处理程序类中的所有异常,包括404s,你可以随心所欲地处理它们。

最后一点--似乎没有一种方法可以让它捕捉抛出的错误。我有一个奇怪的想法,就是使用方面来捕获错误,并将它们转换为异常,然后上面的代码就可以处理这些异常,但是我还没有时间去实际尝试实现它。希望这对某人有帮助。

如有任何意见/更正/改进,将不胜感激。

 类似资料:
  • 我正在使用quarkus版本,需要知道如何处理未知endpoint。当我试图命中尚未实现的endpoint时,它只会发送,而不是我希望实现的异常。我无法找到相同的实现。有人能帮我做这个吗?

  • 问题内容: 我正在尝试建立一个大型的REST服务服务器。我们正在使用Spring Boot 1.2.1,Spring 4.1.5和Java8。我们的控制器正在实现@RestController和标准的@RequestMapping注释。 我的问题是Spring Boot为控制器异常设置了默认重定向到/error。从文档: Spring Boot默认提供一个/ error映射,以一种明智的方式处理所

  • 问题内容: 如果我的Dao层抛出了Dao特定的异常,那么在我的服务层中对它们的处理是否会引起关注的泄漏?如果是,那么我应该使异常通用且独立于任何层来解决它,还是有其他方法吗? 相同的问题适用于服务层引发的UI层处理异常。 问题答案: 当我们创建一个分层的应用程序时,总是有一个用户层和另一个使用过的层。对于这种情况,UI层->使用服务层->使用DAO层。 现在,它非常主观并且易于解释。但目标应该是

  • Java异常处理分为错误、已检查异常和未检查异常。这个问题是关于例外的。 正常的Java异常处理是扩展检查异常的异常类,并通过考虑异常层次结构来处理您需要的异常。 例如: 但是我看到了主要的Spring书籍,甚至在Spring boot中提到的Internet教程中,以及在微服务的上下文中,总是从RuntimeException类扩展而来,即使使用@ControllerAdvice。 这显然违反了

  • 我有一个WCF服务,它连接到一个服务总线队列,准备接收消息。这是工作很好,但我希望能够标记的消息作为一个死信,如果我有一个问题处理的消息。当前,如果我的代码抛出异常,消息仍然会从队列中删除,但我希望能够在配置中指定不从队列中删除,但将其标记为死信。我做了一些搜索,但我不知道怎么做。我当前正在将该服务作为windows服务运行 Uri baseAddress=ServiceBusEnvironmen

  • 因此,我在Spring Boot服务中定义了各种APIendpoint,它们抛出各种自定义异常。但我无法区分已检查和未检查的执行。 那么,我的自定义例外是要检查还是不检查? 示例: UserNotFoundException EmailAlreadyExistsException JWTTokenMalformedException 数据库NodeFailureException 这些异常由Spr