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

Spring Boot-使用RestControllerAdvice的全局自定义异常处理机制

樊胜
2023-03-14

我正在使用Spring Boot for Restful Web Services。

试图建立一个依赖@RestControllerAdvice的全局html" target="_blank">自定义异常处理机制,该机制可以处理已知但未知的异常。

pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.4.RELEASE</version>
</parent>

<properties>
    <java.version>1.8</java.version>
</properties>

<repositories>
    <repository>
        <id>spring-releases</id>
        <url>https://repo.spring.io/libs-release</url>
    </repository>
</repositories>

<pluginRepositories>
    <pluginRepository>
        <id>spring-releases</id>
        <url>https://repo.spring.io/libs-release</url>
    </pluginRepository>
</pluginRepositories>

<dependencies>
    <!-- Spring -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

GlobalControlllerExceptionHandler:

@RestControllerAdvice
public class GlobalControllerExceptionHandler {

    private static final Logger LOG = Logger.getLogger(GlobalControllerExceptionHandler.class);

    @ExceptionHandler(value = { ConstraintViolationException.class })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ApiErrorResponse constraintViolationException(ConstraintViolationException ex) {
        LOG.error(ex.getCause().toString());
        return new ApiErrorResponse(400, "Bad Request");
    }

    @ExceptionHandler(value = { NoHandlerFoundException.class })
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ApiErrorResponse noHandlerFoundException(Exception ex) {
        LOG.error(ex.getCause().toString());
        return new ApiErrorResponse(404, "Resource Not Found");
    }

    @ExceptionHandler(value = { Exception.class })
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ApiErrorResponse unknownException(Exception ex) {
        LOG.error(ex.getCause().toString());
        return new ApiErrorResponse(500, "Internal Server Error");
    }
}

响应:

public class ApiErrorResponse {

    private int status;
    private String message;

    public ApiErrorResponse(int status, String message) {
        this.status = status;
        this.message = message;
    }

    public int getStatus() {
        return status;
    }

    public String getMessage() {
        return message;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this).append(status)
                                        .append(message)
                                        .toString();
    }
}

这个问题是当我使用第三方库做某事时,未知异常可能是404,但返回为500!

例如,使用具有未知索引的ElasticSearch(故意查看异常类型):

{
  "timestamp": 1501236796640,
  "status": 500,
  "error": "Internal Server Error",
  "exception": "org.elasticsearch.client.ResponseException",
  "message": "POST http://localhost:9200/fn3r4343/_search?pretty=true: HTTP/1.1 404 Not Found"
        {
        "error": {
            "root_cause": [
                {
                    "type": "index_not_found_exception",
                    "reason": "no such index",
                    "resource.type": "index_or_alias",
                    "resource.id": "fn3r4343",
                    "index_uuid": "_na_",
                    "index": "fn3r4343"
                }
            ],
            "type": "index_not_found_exception",
            "reason": "nosuchindex",
            "resource.type": "index_or_alias",
            "resource.id": "fn3r4343",
            "index_uuid": "_na_",
            "index": "fn3r4343"
        }
        {  "root_cause" : 
            [ 
                { 
                   "type" :"index_not_found_exception", 
                   "reason" : no such index", "resource.type" : "index_or_alias", 
                   "resource.id" : "fn3r4343",
                   "index_uuid" : "_na_",
                   "index" : "fn3r4343"
                }
            ],
            [  
                    {
                  "type" : "index_not_found_exception",
                  "reason" : "no such index", 
                  "resource.type" : "index_or_alias", 
                  "resource.id" : "fn3r4343", 
                  "index_uuid" : "_na_", 
                  "index" : "fn3r4343"  
                }, 
              "status": 404
              ]
        }
        "path": "/myapp/search"
}

正如你所看到的,它返回HTTP 500状态,但在有效负载中,它实际上是HTTP 404!

我想要回报的是:

{ 
    "message" : "Index Not Found Exception",
    "status"  : "HTTP 404"
}

对于已知的HTTP 404例外:

{ 
    "message" : "Not Found",
    "status"  : "HTTP 404"
}

使用RestControllerAdvice捕捉任何类型的异常,并将响应定制为JSON格式(对于使用REST API的客户端来说是可读的/有用的),是否有良好的实践/机制?

这篇文章并不是专门针对弹性搜索的,而是试图通过使用@RestControllerAdvice来处理任何类型的异常,从而为客户端应用程序提供正确的响应。。。

共有2个答案

潘凯
2023-03-14

我认为下面这节课应该有帮助:

@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {


@ExceptionHandler(value = {MyException.class})
protected ResponseEntity<Object> handleConflict(Exception exception, WebRequest request) 
{
    FinalResponse response =  new FinalResponse()//Define this Bean in a way that it contains all required paramteres to be sent in response when exception occurs
    response.setErrorCd("123");
    response.setMessage("Exception while processing.");
    if (exception instanceof MyException) 
    {
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }
    else 
    {
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
}
公孙慎之
2023-03-14

引发的基本异常是org。弹性搜索。客户ResponseException(您可能正在使用低级REST客户端)。

因此,在您的建议中,您需要为该异常添加一个处理程序,并返回底层状态代码:

@ExceptionHandler(value = { ResponseException.class })
public ApiErrorResponse noHandlerFoundException(Exception ex) {
    LOG.error(ex.getCause().toString());
    int status = ((ResponseException) ex).getResponse().getStatusLine().getStatusCode();
    return new ApiErrorResponse(status, "<some message depending on status code>");
}
 类似资料:
  • 本文向大家介绍Springboot之自定义全局异常处理的实现,包括了Springboot之自定义全局异常处理的实现的使用技巧和注意事项,需要的朋友参考一下 前言: 在实际的应用开发中,很多时候往往因为一些不可控的因素导致程序出现一些错误,这个时候就要及时把异常信息反馈给客户端,便于客户端能够及时地进行处理,而针对代码导致的异常,我们一般有两种处理方式,一种是throws直接抛出,一种是使用try.

  • 本文向大家介绍springboot全局异常处理详解,包括了springboot全局异常处理详解的使用技巧和注意事项,需要的朋友参考一下 一、单个controller范围的异常处理 说明: 在controller中加入被@ExceptionHandler修饰的类即可(在该注解中指定该方法需要处理的那些异常类) 该异常处理方法只在当前的controller中起作用 二、全部controller范围内起

  • 本文向大家介绍SpringBoot错误处理机制以及自定义异常处理详解,包括了SpringBoot错误处理机制以及自定义异常处理详解的使用技巧和注意事项,需要的朋友参考一下 上篇文章我们讲解了使用Hibernate Validation来校验数据,当校验完数据后,如果发生错误我们需要给客户返回一个错误信息,因此这节我们来讲解一下SpringBoot默认的错误处理机制以及如何自定义异常来处理请求错误。

  • 本文向大家介绍springboot全局异常处理代码实例,包括了springboot全局异常处理代码实例的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了springboot全局异常处理代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言: 开发中异常的处理必不可少,常用的就是 throw 和 try catch,这样一个项目到最

  • 本文向大家介绍laravel框架 api自定义全局异常处理方法,包括了laravel框架 api自定义全局异常处理方法的使用技巧和注意事项,需要的朋友参考一下 api返回实现 api返回信息 1,添加异常类 2,修改laravel异常类u。。。 考虑开发配置时 以上这篇laravel框架 api自定义全局异常处理方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊教程。

  • 统一错误处理 文档:https://eggjs.org/zh-cn/tutorials/restful.html 自定义一个异常基类 // app / exceptions / http_exceptions.js class HttpExceptions extends Error { constructor(msg='服务器异常', code=1, httpCode=400) {