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

@ExceptionHandler在处理用户定义的异常时从RuntimeException返回大量日志

壤驷雅达
2023-03-14

我正在学习Spring boot框架。我试图通过使用@ExceptionHandler在控制器级别实现异常处理。我能够处理抛出的用户定义异常,该异常扩展了RuntimeException,但响应比我想要看到的要多得多。它包含来自运行时异常类的原因、堆栈跟踪,但我不希望它们出现在响应中。

下面是@ExceptionHandler的代码

@ExceptionHandler(InvalidPassengerNameException.class)
    public ResponseEntity<InvalidPassengerNameException> handleInvalidPassengerNameException(InvalidPassengerNameException exc) {
        InvalidPassengerNameException iPNE =  new InvalidPassengerNameException();
        iPNE.setErrorCode("E400");
        iPNE.setErrorMessage("PAssenger name should be more than 8 characters");
        return new ResponseEntity<InvalidPassengerNameException>(iPNE, HttpStatus.NOT_ACCEPTABLE);
    }

以下是我的用户定义异常类:

public class InvalidPassengerNameException extends RuntimeException{
private String errorCode;
private String errorMessage;
public String getErrorCode() {
    return errorCode;
}
public void setErrorCode(String errorCode) {
    this.errorCode = errorCode;
}
public String getErrorMessage() {
    return errorMessage;
}
public void setErrorMessage(String errorMessage) {
    this.errorMessage = errorMessage;
}
}

当异常由已定义的处理程序处理时,日志中包含的内容比我想看到的要多得多:

{
    "cause": null,
    "stackTrace": [
        {
            "methodName": "handleInvalidPassengerNameException",
            "fileName": "PassengerController.java",
            "lineNumber": 32,
            "className": "com.booking.application.controller.PassengerController",
            "nativeMethod": false
        },
        {
            "methodName": "invoke0",
            "fileName": "NativeMethodAccessorImpl.java",
            "lineNumber": -2,
            "className": "sun.reflect.NativeMethodAccessorImpl",
            "nativeMethod": true
        },
        {
            "methodName": "invoke",
            "fileName": "NativeMethodAccessorImpl.java",
            "lineNumber": 62,
            "className": "sun.reflect.NativeMethodAccessorImpl",
            "nativeMethod": false
        },
        {
            "methodName": "invoke",
            "fileName": "DelegatingMethodAccessorImpl.java",
            "lineNumber": 43,
            "className": "sun.reflect.DelegatingMethodAccessorImpl",
            "nativeMethod": false
        },
        {
            "methodName": "invoke",
            "fileName": "Method.java",
            "lineNumber": 498,
            "className": "java.lang.reflect.Method",
            "nativeMethod": false
        },
        {
            "methodName": "doInvoke",
            "fileName": "InvocableHandlerMethod.java",
            "lineNumber": 190,
            "className": "org.springframework.web.method.support.InvocableHandlerMethod",
            "nativeMethod": false
        },
        {
            "methodName": "invokeForRequest",
            "fileName": "InvocableHandlerMethod.java",
            "lineNumber": 138,
            "className": "org.springframework.web.method.support.InvocableHandlerMethod",
            "nativeMethod": false
        },
        {
            "methodName": "invokeAndHandle",
            "fileName": "ServletInvocableHandlerMethod.java",
            "lineNumber": 106,
            "className": "org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod",
            "nativeMethod": false
        },
        {
            "methodName": "doResolveHandlerMethodException",
            "fileName": "ExceptionHandlerExceptionResolver.java",
            "lineNumber": 407,
            "className": "org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver",
            "nativeMethod": false
        },
        {
            "methodName": "doResolveException",
            "fileName": "AbstractHandlerMethodExceptionResolver.java",
            "lineNumber": 61,
            "className": "org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver",
            "nativeMethod": false
        },
        {
            "methodName": "resolveException",
            "fileName": "AbstractHandlerExceptionResolver.java",
            "lineNumber": 141,
            "className": "org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver",
            "nativeMethod": false
        },
        {
            "methodName": "resolveException",
            "fileName": "HandlerExceptionResolverComposite.java",
            "lineNumber": 80,
            "className": "org.springframework.web.servlet.handler.HandlerExceptionResolverComposite",
            "nativeMethod": false
        },
        {
            "methodName": "processHandlerException",
            "fileName": "DispatcherServlet.java",
            "lineNumber": 1300,
            "className": "org.springframework.web.servlet.DispatcherServlet",
            "nativeMethod": false
        },
        {
            "methodName": "processDispatchResult",
            "fileName": "DispatcherServlet.java",
            "lineNumber": 1111,
            "className": "org.springframework.web.servlet.DispatcherServlet",
            "nativeMethod": false
        },
        {
            "methodName": "doDispatch",
            "fileName": "DispatcherServlet.java",
            "lineNumber": 1057,
            "className": "org.springframework.web.servlet.DispatcherServlet",
            "nativeMethod": false
        },
        {
            "methodName": "doService",
            "fileName": "DispatcherServlet.java",
            "lineNumber": 943,
            "className": "org.springframework.web.servlet.DispatcherServlet",
            "nativeMethod": false
        },
        {
            "methodName": "processRequest",
            "fileName": "FrameworkServlet.java",
            "lineNumber": 1006,
            "className": "org.springframework.web.servlet.FrameworkServlet",
            "nativeMethod": false
        },
        {
            "methodName": "doPost",
            "fileName": "FrameworkServlet.java",
            "lineNumber": 909,
            "className": "org.springframework.web.servlet.FrameworkServlet",
            "nativeMethod": false
        },
        {
            "methodName": "service",
            "fileName": "HttpServlet.java",
            "lineNumber": 660,
            "className": "javax.servlet.http.HttpServlet",
            "nativeMethod": false
        },
        {
            "methodName": "service",
            "fileName": "FrameworkServlet.java",
            "lineNumber": 883,
            "className": "org.springframework.web.servlet.FrameworkServlet",
            "nativeMethod": false
        },
        {
            "methodName": "service",
            "fileName": "HttpServlet.java",
            "lineNumber": 741,
            "className": "javax.servlet.http.HttpServlet",
            "nativeMethod": false
        },
        {
            "methodName": "internalDoFilter",
            "fileName": "ApplicationFilterChain.java",
            "lineNumber": 231,
            "className": "org.apache.catalina.core.ApplicationFilterChain",
            "nativeMethod": false
        },
        {
            "methodName": "doFilter",
            "fileName": "ApplicationFilterChain.java",
            "lineNumber": 166,
            "className": "org.apache.catalina.core.ApplicationFilterChain",
            "nativeMethod": false
        },
        {
            "methodName": "doFilter",
            "fileName": "WsFilter.java",
            "lineNumber": 53,
            "className": "org.apache.tomcat.websocket.server.WsFilter",
            "nativeMethod": false
        },
        {
            "methodName": "internalDoFilter",
            "fileName": "ApplicationFilterChain.java",
            "lineNumber": 193,
            "className": "org.apache.catalina.core.ApplicationFilterChain",
            "nativeMethod": false
        },
        {
            "methodName": "doFilter",
            "fileName": "ApplicationFilterChain.java",
            "lineNumber": 166,
            "className": "org.apache.catalina.core.ApplicationFilterChain",
            "nativeMethod": false
        },
        {
            "methodName": "doFilterInternal",
            "fileName": "RequestContextFilter.java",
            "lineNumber": 100,
            "className": "org.springframework.web.filter.RequestContextFilter",
            "nativeMethod": false
        },
        {
            "methodName": "doFilter",
            "fileName": "OncePerRequestFilter.java",
            "lineNumber": 119,
            "className": "org.springframework.web.filter.OncePerRequestFilter",
            "nativeMethod": false
        },
        {
            "methodName": "internalDoFilter",
            "fileName": "ApplicationFilterChain.java",
            "lineNumber": 193,
            "className": "org.apache.catalina.core.ApplicationFilterChain",
            "nativeMethod": false
        },
        {
            "methodName": "doFilter",
            "fileName": "ApplicationFilterChain.java",
            "lineNumber": 166,
            "className": "org.apache.catalina.core.ApplicationFilterChain",
            "nativeMethod": false
        },
        {
            "methodName": "doFilterInternal",
            "fileName": "FormContentFilter.java",
            "lineNumber": 93,
            "className": "org.springframework.web.filter.FormContentFilter",
            "nativeMethod": false
        },
        {
            "methodName": "doFilter",
            "fileName": "OncePerRequestFilter.java",
            "lineNumber": 119,
            "className": "org.springframework.web.filter.OncePerRequestFilter",
            "nativeMethod": false
        },
        {
            "methodName": "internalDoFilter",
            "fileName": "ApplicationFilterChain.java",
            "lineNumber": 193,
            "className": "org.apache.catalina.core.ApplicationFilterChain",
            "nativeMethod": false
        },
        {
            "methodName": "doFilter",
            "fileName": "ApplicationFilterChain.java",
            "lineNumber": 166,
            "className": "org.apache.catalina.core.ApplicationFilterChain",
            "nativeMethod": false
        },
        {
            "methodName": "doFilterInternal",
            "fileName": "CharacterEncodingFilter.java",
            "lineNumber": 201,
            "className": "org.springframework.web.filter.CharacterEncodingFilter",
            "nativeMethod": false
        },
        {
            "methodName": "doFilter",
            "fileName": "OncePerRequestFilter.java",
            "lineNumber": 119,
            "className": "org.springframework.web.filter.OncePerRequestFilter",
            "nativeMethod": false
        },
        {
            "methodName": "internalDoFilter",
            "fileName": "ApplicationFilterChain.java",
            "lineNumber": 193,
            "className": "org.apache.catalina.core.ApplicationFilterChain",
            "nativeMethod": false
        },
        {
            "methodName": "doFilter",
            "fileName": "ApplicationFilterChain.java",
            "lineNumber": 166,
            "className": "org.apache.catalina.core.ApplicationFilterChain",
            "nativeMethod": false
        },
        {
            "methodName": "invoke",
            "fileName": "StandardWrapperValve.java",
            "lineNumber": 202,
            "className": "org.apache.catalina.core.StandardWrapperValve",
            "nativeMethod": false
        },
        {
            "methodName": "invoke",
            "fileName": "StandardContextValve.java",
            "lineNumber": 96,
            "className": "org.apache.catalina.core.StandardContextValve",
            "nativeMethod": false
        },
        {
            "methodName": "invoke",
            "fileName": "AuthenticatorBase.java",
            "lineNumber": 526,
            "className": "org.apache.catalina.authenticator.AuthenticatorBase",
            "nativeMethod": false
        },
        {
            "methodName": "invoke",
            "fileName": "StandardHostValve.java",
            "lineNumber": 139,
            "className": "org.apache.catalina.core.StandardHostValve",
            "nativeMethod": false
        },
        {
            "methodName": "invoke",
            "fileName": "ErrorReportValve.java",
            "lineNumber": 92,
            "className": "org.apache.catalina.valves.ErrorReportValve",
            "nativeMethod": false
        },
        {
            "methodName": "invoke",
            "fileName": "StandardEngineValve.java",
            "lineNumber": 74,
            "className": "org.apache.catalina.core.StandardEngineValve",
            "nativeMethod": false
        },
        {
            "methodName": "service",
            "fileName": "CoyoteAdapter.java",
            "lineNumber": 343,
            "className": "org.apache.catalina.connector.CoyoteAdapter",
            "nativeMethod": false
        },
        {
            "methodName": "service",
            "fileName": "Http11Processor.java",
            "lineNumber": 367,
            "className": "org.apache.coyote.http11.Http11Processor",
            "nativeMethod": false
        },
        {
            "methodName": "process",
            "fileName": "AbstractProcessorLight.java",
            "lineNumber": 65,
            "className": "org.apache.coyote.AbstractProcessorLight",
            "nativeMethod": false
        },
        {
            "methodName": "process",
            "fileName": "AbstractProtocol.java",
            "lineNumber": 860,
            "className": "org.apache.coyote.AbstractProtocol$ConnectionHandler",
            "nativeMethod": false
        },
        {
            "methodName": "doRun",
            "fileName": "NioEndpoint.java",
            "lineNumber": 1591,
            "className": "org.apache.tomcat.util.net.NioEndpoint$SocketProcessor",
            "nativeMethod": false
        },
        {
            "methodName": "run",
            "fileName": "SocketProcessorBase.java",
            "lineNumber": 49,
            "className": "org.apache.tomcat.util.net.SocketProcessorBase",
            "nativeMethod": false
        },
        {
            "methodName": "runWorker",
            "fileName": "ThreadPoolExecutor.java",
            "lineNumber": 1149,
            "className": "java.util.concurrent.ThreadPoolExecutor",
            "nativeMethod": false
        },
        {
            "methodName": "run",
            "fileName": "ThreadPoolExecutor.java",
            "lineNumber": 624,
            "className": "java.util.concurrent.ThreadPoolExecutor$Worker",
            "nativeMethod": false
        },
        {
            "methodName": "run",
            "fileName": "TaskThread.java",
            "lineNumber": 61,
            "className": "org.apache.tomcat.util.threads.TaskThread$WrappingRunnable",
            "nativeMethod": false
        },
        {
            "methodName": "run",
            "fileName": "Thread.java",
            "lineNumber": 748,
            "className": "java.lang.Thread",
            "nativeMethod": false
        }
    ],
    "errorCode": "E400",
    "errorMessage": "Passenger name should be more than 8 characters",
    "localizedMessage": null,
    "message": null,
    "suppressed": []
}

我想看到的是:

"errorCode": "E400",
"errorMessage": "Passenger name should be more than 8 characters",

我错过了什么?我知道一个全局@控制者建议会有所帮助。但是我想知道为什么会发生这种情况,以及如何实现这种情况以实现预期的输出响应?

共有1个答案

华章横
2023-03-14

@ExceptionHandler工作正常。但是,您正在扩展运行时异常,它附带了一个getCause()getStackTrace()。Jackson将所有这些字段序列化为JSON,这就是为什么会看到一个stacktrace和一个cause字段。

为了解决这个问题,您可以为您的错误创建一个专用的DTO,该DTO不从RuntimeExctive扩展,例如:

public class ErrorMessageDTO {
    private final String errorCode;
    private final String errorMessage;

    // Constructors + Getters + Setters
}

现在你可以在你的@ExceptionHandler中使用这个:

@ExceptionHandler(InvalidPassengerNameException.class)
public ResponseEntity<ErrorMessageDTO> handleInvalidPassengerNameException(InvalidPassengerNameException exc) {
    ErrorMessageDTO message = new ErrorMessageDTO("E400", "Passenger name should be more than 8 characters");
    return new ResponseEntity<ErrorMessageDTO>(message, HttpStatus.NOT_ACCEPTABLE);
}

或者,您可以覆盖RuntimeException的getter,并用@JsonIgnore注释它们:

public class InvalidPassengerNameException extends RuntimeException {
    // Fields + Getters + Setters

    @JsonIgnore
    @Override
    public Throwable getCause() {
        return super.getCause();
    }
}

在这种情况下,第一种解决方案是最好的。您已经在@ExceptionHandler中返回了一个新对象,这个新对象不再需要从RuntimeException扩展。

 类似资料:
  • 我有例外: 其他自定义异常从它继承: 处理它们。现在看起来就像是在那里: ExceptionHandler正确处理所有自定义异常,排除 在验证jwm-token时,此异常只在一种情况下抛出。 这样,Console中有3个stacktraces日志: 仅前端重装 请告诉我,怎么了。 附注。完整StackTrace: null 2019-07-14 17:04:38.791错误24060---[nio

  • 我使用Spring的@ControllerAdvice和@ExceptionHandler进行异常处理。任何方法都会从Controller中抛出自定义异常,并由相应的@ExceptionHandler处理它。如果发生运行时异常(例如任何HibernateException),那么它将抛出运行时异常,并且我没有任何@ExceptionHandler用于运行时异常。

  • 我想定义一个返回int的异常。下面给出了我的代码。它显示出错误。 solution.cc:12:22:错误:为“virtual const int BadLengthException::what()const throw()”{^~~~指定的返回类型冲突,该文件包含的文件来自/usr/include/C++/7/Exception:38:0、来自/usr/include/C++/7/IOS:39

  • 问题内容: 我正在使用FQL从Facebook检索用户列表。为了一致性,我将结果作为JSON。这就引起了一个问题- 由于返回的JSON将用户ID编码为数字,因此json_decode()会将这些数字转换为浮点值,因为其中有些太大而不能容纳在int中;当然,我需要这些ID作为字符串。 由于json_decode()在不接受任何行为标志的情况下做自己的事情,所以我很茫然。有关如何解决此问题的任何建议?

  • 本文向大家介绍Java异常处理运行时异常(RuntimeException)详解及实例,包括了Java异常处理运行时异常(RuntimeException)详解及实例的使用技巧和注意事项,需要的朋友参考一下   Java异常处理运行时异常(RuntimeException)详解及实例 RuntimeException RunntimeException的子类: ClassCastException

  • 1.【强制】不要捕获Java类库中定义的继承自RuntimeException的运行时异常类,如:IndexOutOfBoundsException / NullPointerException,这类异常由程序员预检查来规避,保证程序健壮性。 正例:if(obj != null) {...} 反例:try { obj.method() } catch(NullPointerException e)