使用Jackson的Spring REST - 400错误请求记录

Eur*_*nes 37 spring spring-mvc

我使用Jackson/JSON设置了Spring REST,一切正常.

但我故意在消息结构中引入了一个错误,导致了400错误的请求.但是服务器上没有日志输出.我期待的错误将是"杰克逊未知属性异常"或其他什么,但它被捕获并且400错误被发送到客户端,但没有在服务器上的异常日志.

我不想清楚地调试服务器上的所有内容,但我希望像这样的Spring网络级异常明确标记为错误.

打开它的正确方法是什么?

谢谢!

Juk*_*kka 42

@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
public void handle(HttpMessageNotReadableException e) {
    logger.warn("Returning HTTP 400 Bad Request", e);
}
Run Code Online (Sandbox Code Playgroud)

  • 就我记忆所言,Spring确实将它们记录在DEBUG级别.请注意,您可以将此异常处理程序方法放在超类中.此外,如果您想要将错误消息返回给客户端(除状态代码外),这就是您要做的. (4认同)
  • 当然有更通用的方法吗?我会想象抛出这些异常的 spring 框架在抛出异常之前会有一个日志调用。 (3认同)
  • -1 - 随机代码存根,但不解释您要实现的目标。这是去哪儿?这是做什么的?请解释 (3认同)
  • 映射的 @ExceptionHandler 方法不明确 (2认同)

Dav*_*lch 36

在@ Jukka的回答基础上,您可以使用@ControllerAdvice(在Spring 3.2中引入的)所有控制器全局启用它.它确实需要一些代码,但根据我的经验,您通常最终需要一个全局错误处理配置,这允许您设置断点/轻松检查问题.

下面是一个例子:

@ControllerAdvice
public class ControllerConfig {

    @ExceptionHandler
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public void handle(HttpMessageNotReadableException e) {
        log.warn("Returning HTTP 400 Bad Request", e);
        throw e;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 很有帮助.但是一定要把你的ControllerAdvice放在Spring扫描的包中:我的第一次尝试失败了,因为我把它放在一个相当通用的方法 - 在另一个比我的控制器更通用的包中,所以它没有被Spring注意到. (7认同)
  • 这似乎不再起作用了,因为 Spring 现在在其 `ResponseEntityExceptionHandler#handleException` 方法中为 `HttpMessageNotReadableException` 添加了一个 `@ExceptionHandler` 注释。当我将上述内容添加到我的代码中时,我收到此错误:“java.lang.IllegalStateException:为[class org.springframework.http.converter.HttpMessageNotReadableException]映射的模糊@ExceptionHandler方法”,因为我的异常映射器与Spring的冲突。 (2认同)

小智 13

您可以log在 中设置此属性的调试级别application.properties

logging.level.org.springframework.web= DEBUG
Run Code Online (Sandbox Code Playgroud)


Mik*_*ike 10

万一其他人在这个问题上迷路了,以下内容在Spring Boot 2 / Spring 5中对我有用,不需要更改代码。

我设置日志级别org.springframework.web.servlet.mvc.method.annotationDEBUG。就我而言,我在客户端代码中看到了400个响应,但是在服务器端却没有日志记录(即使使用自定义错误处理程序)。更改该日志级别后,问题很明显:

DEBUG 172.19.0.16     cs              2018-Jun-08 20:55:08.415 [https-jsse-nio-443-exec-9] - method.annotation.RequestResponseBodyMethodProcessor[line ?] - Read [class java.lang.String] as "application/xml;charset=UTF-8" with [org.springframework.http.converter.xml.MarshallingHttpMessageConverter@2de50ee4]
DEBUG 172.19.0.16     cs              2018-Jun-08 20:55:08.418 [https-jsse-nio-443-exec-9] - method.annotation.ServletInvocableHandlerMethod[line ?] - Failed to resolve argument 0 of type 'java.lang.String'
org.springframework.beans.TypeMismatchException: Failed to convert value of type 'core.dto.RequestDTO' to required type 'java.lang.String'
Run Code Online (Sandbox Code Playgroud)

  • 这是最好的选择,应改为接受:您可以在检查请求/响应映射/杰克逊转换详细信息和失败时将根日志级别保持为WARN,并且不需要额外的异常处理程序。这样,您就不会迷失在原木行上。 (5认同)
  • 或者使用 SpringBoot 只需添加一个环境变量(例如,对于 Kubernetes/OpenShift,直接添加到 ConfigMap): LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB_SERVLET_MVC_METHOD_ANNOTATION: DEBUG (3认同)
  • 使用 Spring Boot,您只需将 -Ddebug 添加到 VM 选项中即可。 (2认同)

小智 8

就我而言,问题出在我的@ControllerAdvice-annoted 类中,该类扩展了ResponseEntityExceptionHandler. 当我从一些关于自定义异常处理的随机教程中获得该处理程序代码时,我没有费心去检查该超类正在做什么(我的自定义异常处理工作得很好)。

问题是与其他 Spring MVC 异常一起ResponseEntityExceptionHandler.handleException()处理,将处理逻辑委托给特定的处理方法。MethodArgumentNotValidException由于我没有为任何此类方法(在本例中handleMethodArgumentNotValid())提供返回我自己的响应正文的实现,因此我最终得到了返回带有空正文的响应的默认实现:)。

解决方案

重写您需要的方法或根本不扩展该类。

检查ResponseEntityExceptionHandler 文档以获取已实现的处理程序方法的列表。