Java 防止Spring引导应用程序中自定义异常的堆栈跟踪日志记录
在Spring Boot(mvc)中有没有一种方法可以记录一个自定义异常,并在日志文件中不显示其堆栈跟踪的情况下抛出它?但对于任何其他异常,仍然可以看到堆栈跟踪 详细解释: 我正在使用SpringBoot创建一个简单的rest服务我喜欢自定义异常,默认情况下日志中没有堆栈跟踪,json响应使用基本异常详细信息(状态、错误、消息)创建 问题是,它也不会创建任何日志条目,因此我必须手动执行此操作: 自定义异常Java 防止Spring引导应用程序中自定义异常的堆栈跟踪日志记录,java,spring,logging,exception-handling,spring-boot,Java,Spring,Logging,Exception Handling,Spring Boot,在Spring Boot(mvc)中有没有一种方法可以记录一个自定义异常,并在日志文件中不显示其堆栈跟踪的情况下抛出它?但对于任何其他异常,仍然可以看到堆栈跟踪 详细解释: 我正在使用SpringBoot创建一个简单的rest服务我喜欢自定义异常,默认情况下日志中没有堆栈跟踪,json响应使用基本异常详细信息(状态、错误、消息)创建 问题是,它也不会创建任何日志条目,因此我必须手动执行此操作: 自定义异常 @ResponseStatus(value = HttpStatus.CONFLICT)
@ResponseStatus(value = HttpStatus.CONFLICT)
public class DuplicateFoundException extends RuntimeException {
public DuplicateFoundException(String message) {
super(message);
}
}
在服务方法中引发异常(在@RestController中)
有更多的异常会导致在每次抛出之前放置log语句,我认为这是一种糟糕的方法。我已尝试从服务方法中删除所有日志语句,并创建了@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;
}
}
现在的问题是,我不仅看到了日志条目,还看到了自定义异常的堆栈跟踪,无法找到防止这种情况发生的方法。
我认为问题是由于再次投掷造成的。一个可能的解决方案是为异常创建一个自定义类,我将返回该类,但我不喜欢这种想法,因为异常编组似乎工作正常
有什么提示吗?谢谢。如果不需要堆栈跟踪,可以通过在异常类中重写
fillInStackTrace
来抑制堆栈跟踪
public class DuplicateFoundException extends RuntimeException {
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}
调用e.printStackTrace()
时,将不打印堆栈跟踪
另请参见。解决方案是将异常处理留给spring boot,以便不记录自定义异常,而默认情况下记录任何其他异常。我从rest控制器中删除了@ControllerAdvice和日志语句,并将日志语句添加到自定义异常构造函数中
public DuplicateFoundException(String message) {
super(message);
LOGGER.warn(message);
}
我不确定这是否是最好的方法,但现在我只在一个地方有自定义异常日志记录,不必为每个异常重复log语句,也不必在日志中看到其堆栈跟踪或任何其他错误消息。我使用的是Spring Boot 2+
只需将此行添加到应用程序。属性:
server.error.include stacktrace=never
小心弹簧靴开发工具 尽管
服务器的默认设置是从不。错误。包括stacktrace
,但如果包括Spring Boot开发工具,它将始终覆盖
如果您对更多细节感兴趣,请参阅,它已成为SpringBoot2.1.0的一部分+
调用重载的超级构造函数以避免在响应中显示堆栈跟踪
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);
}
}
谢谢,堆栈跟踪已消失,但我仍然看到“2015-07-07 11:47:57.188错误41456---[nio-8080-exec-1].m.a.ExceptionHandlerExceptionResolver:未能调用@ExceptionHandler方法:public org.springframework.web.servlet.ModelAndView”。有没有一种方法可以消除这个问题,这样我就不会在自定义异常的日志中看到任何错误?我接受了这个答案,因为堆栈跟踪消失了,但是现在我看到我的异常消息在日志中出现了两次(1.log语句和2.failed方法的异常消息),我认为没有简单的方法可以做到这一点。也许您应该考虑不使用异常(即自定义状态代码),因为这种情况并不例外,但可以预期。我的用例基本上与官方springdoc()中的示例相同,因此我不认为它是可预期的。否则,我们也可以讨论validationException的意义。正如我在问题中所描述的,创建自定义返回对象是可能的,但如果可能的话,我试图找到更简单、更干净的解决方案。@RolandWeisleer谢谢你的回答,它真的帮助了我。因此,它进入了log.warn
行,但也记录了整个异常?我可能错了,但我以前见过@ExceptionHandler
s不抛出,它们只返回一个ResponseEntity
(状态为500等),而不是FWIW…从1.3.0开始,默认为“从不”。检查@shark1608,因为发行说明确实指出,使用SpringBoot2.1.7,它被设置为“始终”default@Robber请看下面我的答案,这也许可以解释为什么它总是被设置为Hanks,欣赏它的彻底性。总是喜欢了解情况的“为什么”部分。还有一个不知道“spring boot魔力”的例子。如果您更新application.yml
(或application.properties
)以指定NEVER
spring boot开发工具将尊重它(至少在2.3版中),检查您是否也覆盖了DefaultErrorAttributes,并且没有使用硬编码的includeStackTrace参数调用getErrorAttributes-就像我刚才所做的,duh!
protected Exception(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}