簡體   English   中英

如何防止 Spring Rest API 異常處理程序返回 HTTP 狀態 400 的堆棧跟蹤

[英]How to Prevent Stack Trace from Spring Rest API Exception Handler returning HTTP status 400

我正在嘗試處理 Spring Rest 服務中的驗證異常,如下所示:

@Produces("application/json")
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public @ResponseBody ResponseEntity<ValidationErrorDTO> processValidationError(MethodArgumentNotValidException ex) {
        BindingResult result = ex.getBindingResult();
        List<FieldError> fieldErrors = result.getFieldErrors();
        ResponseEntity<ValidationErrorDTO> re = new ResponseEntity<>(processFieldErrors(fieldErrors), HttpStatus.BAD_REQUEST);   
        return re;
    }

但是,當此代碼執行時,它會返回附加到 JSON 響應的堆棧跟蹤。 我想擺脫這個堆棧跟蹤,只返回 JSON 錯誤響應。 這在 Spring 3.1 中可行嗎?

{"fieldErrors":    
[{"field":"type","message":"Pattern.shippingAddress.type"}]}&lt;pre&gt;javax.servlet.ServletException: 400 Bad Request null
        at com.ebay.raptor.kernel.dispatcher.HttpDispatchCommand.execute(HttpDispatchCommand.java:142)
        at com.ebay.ebox.pres.cmd.preshandler.CommandDispatchHandler.handleRequest(CommandDispatchHandler.java:59)
        at com.ebay.ebox.pres.cmd.preshandler.CommandDispatchHandler.handleRequest(CommandDispatchHandler.java:13)
        at com.ebay.ebox.pres.cmd.preshandler.CommandHandlerFactory$CalHandler.handleRequest(CommandHandlerFactory.java:114)
        at com.ebay.ebox.pres.cmd.preshandler.CommandHandlerFactory$CalHandler.handleRequest(CommandHandlerFactory.java:75)
        at com.ebay.kernel.pipeline.RequestPipeline.invoke(RequestPipeline.java:18)
        at com.ebay.kernel.pipeline.RequestPipeline.invoke(RequestPipeline.java:12)
        at com.ebay.kernel.pipeline.BasePipeline.callHandler(BasePipeline.java:75)
        at com.ebay.kernel.pipeline.BasePipeline.execute(BasePipeline.java:53)
        at com.ebay.ebox.pres.stage.BaseCommandRequestStageImpl.doWork(BaseCommandRequestStageImpl.java:64)
        at com.ebay.kernel.stage.StageDriver.execute(StageDriver.java:55)
        at com.ebay.ebox.pres.cmd.WebCommandImpl.execute(WebCommandImpl.java:30)
        at com.ebay.raptor.web.RaptorFrontController.process(RaptorFrontController.java:338)
        at com.ebay.raptor.web.RaptorFrontController.doPost(RaptorFrontController.java:554)
        at com.ebay.raptor.web.RaptorGenericController.service(RaptorGenericController.java:64)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:749)
        at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:487)
        at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:379)
        at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:339)
        at com.ebay.raptor.kernel.filter.RaptorDispatchFilter.doFilter(RaptorDispatchFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:195)
        at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:266)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)
    &lt;/pre&gt;

您只需添加應用程序屬性server.error.include-stacktrace=never響應將堆棧跟蹤包含到 400 個響應中。

你可以這樣做:

@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ModelAndView methodArgumentError(HttpServletRequest req, Exception exception) {
    return new JsonError(exception.getMessage()).asModelAndView();
}

如果錯誤僅返回給用戶而不用於調試,則可以在MethodArgumentNotValidException中將堆棧跟蹤設置為 null。

或者,您可以使用@JsonIgnore注釋覆蓋getStackTrace()

@JsonIgnore
@Override
public StackTraceElement[] getStackTrace() {
    return super.getStackTrace();
}

編輯:我嘗試了所有其他解決方案,但沒有一個對我有用。

@Order(Ordered.HIGHEST_PRECEDENCE)

在您的方法上使用 @Order(Ordered.HIGHEST_PRECEDENCE) 它將起作用

同時使用: @ResponseBodyResponseEntity是不常見的。 我認為你應該清楚地決定你想要做什么。 - 然后你應該檢查你的內部框架類com.ebay.raptor.kernel.dispatcher.HttpDispatchCommand ,因為這是拋出異常的那個。

另一種更簡單的方法來做到這一點

public static void main(String[] args) {


System.setProperty("server.error.include-message", "never");
System.setProperty("server.error.include-stacktrace", "never");

//You can also change other important properties with this method, for example:

// System.setProperty("server.port", "8081");
// System.setProperty("server.servlet.context-path", "/api");

SpringApplication.run(YourApplication.class, args);

}

響應將如下所示;

{
    "timestamp": "2021-12-30T19:23:24.002+00:00",
    "status": 400,
    "error": "Bad Request",
    "path": "/test"
}

您可以將 Aspectj 用於這些目的。 示例http://www.mkyong.com/spring3/spring-aop-aspectj-annotation-example/

您應該編寫一個方面,它將捕獲您的異常。

例子:

@Aspect
public class AroundExample {
 @Around
 pointcut = "execution(* your.package.Class.processValidationError(..))",
      throwing= "error")
 public Object doSomeStuff(ProceedingJoinPoint pjp, Throwable error) throws Throwable {

    Object[] args = joinPoint.getArgs(); // change the args if you want to
    Object retVal = pjp.proceed(args); // run the actual method (or don't)
    return retVal; // return the return value (or something else)
  }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM