繁体   English   中英

在 Spring Boot 应用程序中防止自定义异常的堆栈跟踪日志记录

[英]Prevent stack trace logging for custom exception in Spring Boot application

Spring Boot (MVC) 中有没有办法记录自定义异常并在日志文件中不显示其堆栈跟踪的情况下将其抛出? 但是对于任何其他异常,仍然可以查看堆栈跟踪。

长解释:

我正在使用 spring boot 来创建一个简单的休息服务。 我喜欢自定义异常,默认情况下日志中没有堆栈跟踪,并且使用基本异常详细信息(状态、错误、消息)创建 JSON 响应。

问题是它也根本没有创建日志条目,因此我必须手动执行此操作:

自定义异常

@ResponseStatus(value = HttpStatus.CONFLICT)
public class DuplicateFoundException extends RuntimeException {
    public DuplicateFoundException(String message) {
        super(message);
    }
}

服务方法中的异常抛出(在@RestController中)

if (!voteDao.findByItemAndUser(item, voteDto.getUserId()).isEmpty()) {
    log.warn("... already voted ...");   //TODO: don't do this for every throw
    throw new DuplicateFoundException("... already voted ...");
}

有更多的异常会导致在每次抛出之前放置日志语句,我认为这是一种不好的方法。 我尝试从服务方法中删除所有日志语句并创建@ControllerAdvice ,我将在其中记录所有自定义异常并重新抛出它们,这样我仍然可以像以前一样获得漂亮的 JSON:

@ControllerAdvice
public class RestExceptionHandler {
    private static final Logger log = Logger.getLogger(RestExceptionHandler.class);

    @ExceptionHandler
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
            log.warn(e.getMessage());
        } else {
            log.error("...");
        }
        throw e;
    }
}

现在的问题是,我不仅看到了日志条目,还看到了自定义异常的堆栈跟踪,并且找不到防止这种情况的方法。 我认为问题是由于再次抛出它引起的。 一个可能的解决方案是为异常创建一个自定义类,我将返回它,但我不喜欢这个想法,因为异常编组似乎工作正常。

有什么提示吗?

我正在使用 Spring Boot 2+,只需将此行添加到您的 application.properties:

server.error.include-stacktrace=从不

https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/web/ErrorProperties.IncludeStacktrace.html

警惕 Spring Boot DevTools。

尽管NEVER都不是server.error.include-stacktrace的默认值,但如果包含 Spring Boot DevTools 它会覆盖到ALWAYS

如果您对更多细节感兴趣,请参阅此提交,它已成为 Spring Boot 2.1.0+ 的一部分在此处输入图像描述

如果您不需要堆栈跟踪,则可以通过覆盖异常类中的fillInStackTrace来抑制堆栈跟踪。

public class DuplicateFoundException extends RuntimeException {
    @Override
    public synchronized Throwable fillInStackTrace() {
        return this;
    }
}

当您调用e.printStackTrace()时,不会打印堆栈跟踪。

另请参阅此博客文章

调用重载的超级构造函数以避免在响应中显示堆栈跟踪。

public class ProductCustomException extends Exception{
    
    private static final long serialVersionUID = -291211739734090347L;

    public ProductCustomException(String message) {
        super(message,null,false,false);
    }

}

来自异常类的超载构造函数

 protected Exception(String message, Throwable cause,
                        boolean enableSuppression,
                        boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
    
}

解决方案是将异常处理留给 spring boot ,以便不记录自定义异常,默认情况下记录任何其他异常。 我从其余控制器中删除了 @ControllerAdvice 以及日志语句,并将日志语句添加到自定义异常构造函数中。

public DuplicateFoundException(String message) {
    super(message);
    LOGGER.warn(message);
}

我不确定这是否是最好的方法,但现在我只在一个地方有自定义异常日志记录,并且不必为每个异常重复日志语句或查看其堆栈跟踪或日志中的任何其他错误消息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM