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

rho*_*ath 16 java logging spring exception-handling spring-boot

Spring Boot(mvc)中是否有一种方法可以记录自定义异常并抛出它,而不会在日志文件中看到它的堆栈跟踪?但是对于任何其他异常仍然会看到堆栈跟踪.

很长的解释:

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

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

自定义例外

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

抛出服务方法的异常(在@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 ...");
}
Run Code Online (Sandbox Code Playgroud)

有更多的异常导致在每次抛出之前放置日志语句,这是一种我认为不好的方法.我已经尝试从服务方法中删除所有日志语句并创建了@ControlledAdvice,我将记录所有自定义异常并重新抛出它们,所以我仍然像以前一样得到好的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

任何提示?谢谢.

mut*_*nUp 31

警惕 Spring Boot DevTools。

尽管NEVER是默认的server.error.include-stacktrace,如果包括它都不会到春季启动DevTools ALWAYS

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


小智 15

我正在使用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

  • @Robber请参阅下面我的答案,这可能解释了为什么它被设置为“始终” (2认同)

Rol*_*der 10

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

public class DuplicateFoundException extends RuntimeException {
    @Override
    public synchronized Throwable fillInStackTrace() {
        return this;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

另请参阅此博客文章.


rho*_*ath 0

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

public DuplicateFoundException(String message) {
    super(message);
    LOGGER.warn(message);
}
Run Code Online (Sandbox Code Playgroud)

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