Spring MVC for Rest 服务如何在 Jackson 反序列化错误时自定义错误“消息”?

Posted

技术标签:

【中文标题】Spring MVC for Rest 服务如何在 Jackson 反序列化错误时自定义错误“消息”?【英文标题】:Spring MVC for Rest service how do I customize the error "message" when it's a Jackson deserialization error? 【发布时间】:2015-06-01 01:37:21 【问题描述】:

我的 Spring Boot 应用程序中有一个带有单一方法的 RestController。此方法处理对 /foo url 的 POST 请求。它接受一个 ID 和一个 DTO 对象作为参数。 Jackson 正在反序列化 DTO 对象。我已将 @Valid 添加到 DTO 参数以验证正在传递的几个属性。我的问题在于当我为一个应该是 int 的字段传入一个字符串时。这会触发 HttpMessageNotReadableException 并且输出的“消息”包含内部对象表示信息,例如类和包名称。在对@Valid 进行休眠验证之前,此错误发生在某个地方的 Jackson 反序列化逻辑中。我可以在我的控制器中创建一个 @ExceptionHandler 注释方法来处理这些类型的异常,但是我必须手动制作 json 输出或坚持 Spring 使用来自 Jackson 的默认消息。

这是发生此异常时 Spring 输出的内容:


"timestamp": 1427473174263,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "Could not read JSON: Can not construct instance of int from String value 'SHOULDNT BE A STRING': not a valid Integer value\ at [Source: java.io.PushbackInputStream@34070211; line: 1, column: 3] (through reference chain: com.blah.foo.dto.CustomerProductPromotionDTO[\"productId\"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of int from String value 'SHOULDNT BE A STRING': not a valid Integer value\ at [Source: java.io.PushbackInputStream@34070211; line: 1, column: 3] (through reference chain: com.blah.foo.dto.CustomerProductPromotionDTO[\"productId\"])",
"path": "/customers/123456/promotions"

如何自定义“消息”字段?

【问题讨论】:

【参考方案1】:

所以我想出了解决这个 Jackson 错误并仍然使用 Spring 的默认休息响应的最佳方法。我没有意识到您可以将@ExceptionHandler 与@ResponseStatus 一起用于这些非自定义异常类型。

 */
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="There was an error processing the request body.")
public void handleMessageNotReadableException(HttpServletRequest request, HttpMessageNotReadableException exception) 
    LOGGER.error("\nUnable to bind post data sent to: " + request.getRequestURI() + "\nCaught Exception:\n" + exception.getMessage());

【讨论】:

【参考方案2】:

上面的 Spring 输出来自 BasicErrorController,它实现了 ErrorController。所以你可以实现自定义ErrorController来处理来自Spring框架的错误消息的格式。参考https://gist.github.com/jonikarppinen/662c38fb57a23de61c8b

【讨论】:

【参考方案3】:

在你的Controller中,可以添加自定义错误响应的方法:

@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<?> handleMessageNotReadableException(
            HttpServletRequest request, 
            HttpMessageNotReadableException e) 

    //Build your response and send it back

【讨论】:

以上是关于Spring MVC for Rest 服务如何在 Jackson 反序列化错误时自定义错误“消息”?的主要内容,如果未能解决你的问题,请参考以下文章

如何向我的 Spring MVC REST 服务添加错误?

如何正确实现使用 Spring MVC\Boot 返回图像列表的 REST 服务?

如何访问 Spring MVC REST 控制器中的 HTTP 标头信息?

如何在 spring-mvc 中为 REST 查询提供对象列表?

Spring Security + Angular JS + Spring MVC Rest

Spring MVC + Spring Security 登录与一个 REST Web 服务