【问题标题】:Customizing / patching 400 response in REST API在 REST API 中自定义/修补 400 响应
【发布时间】:2019-11-15 23:05:38
【问题描述】:

我已经使用 Spring & Swagger 构建了一个 rest api。持久性是通过 Hibernate 实现的。其余的 api 以不同的格式公开数据,然后它在数据库中,所以我使用的是 dto 模式。客户与 CustomerDto。一切都很好。我用@ApiModel(value="Customer") 掩盖了 Swagger 中的 CustomerDto。这一切也都很好。

这就是问题所在。我正在使用@Size、@NotNull 等验证注释。所以我得到了不错的 400 响应 json:

{
  "timestamp": "2019-11-15T22:25:37.943+0000",
  "status": 400,
  "error": "Bad Request",
  "errors": [
    {
      "codes": [
        "NotNull.customerDto.firstName",

似乎 MethodArgumentNotValidException 不知道 @ApiModel 注释,因此它将对象名称显示为 customerDto。

有什么办法可以修补响应或类似的东西吗?我知道我可以捕获 400 异常并建立自己的响应,但我宁愿不重新发明整个轮子来重现整个 json。

我的公司与金融机构合作,因此出于安全目的,我们不应该透露应用内部信息。

编辑:应该明确表示我不想替换库存 json,我只想将 customerDto 更改为 customer。除了消息之外,json 中还有一些元素,比如代码和东西。也试图接近那些。

【问题讨论】:

标签: java spring swagger


【解决方案1】:

默认情况下,所有错误消息都内置在 DefaultErrorAttributes 中,因此您可以对其进行扩展以修改错误属性映射。

这是一个例子:

 import java.util.Map;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.WebRequest;



     @Component
        public class ExtendedDefaultErrorAttributes extends DefaultErrorAttributes {
          @Override
          public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
            final Map<String, Object> errorAttributes =
                super.getErrorAttributes(webRequest, includeStackTrace);

            // MethodArgumentNotValidException includes errors key
            Object errors = errorAttributes.get("errors");
             // .. now you can do whatever you want here... something like completely remove it.  
            if (errors != null) {
              errorAttributes.remove("errors");
            }


   // In here for what you are looking for , you should be doing something like //below, just as an example, but do it properly, I just typed it without checking:

     List<ObjectError> errors = (List<ObjectError>) errorAttributes.get("errors");

        errors.get(0).getCodes()[0].replaceAll("customerDto", "customer");

            return errorAttributes;
          }
        }

或者在 ControllerAdvice 或 Controller 类中使用 @ExceptionHandler 来根据需要进行修改。

例子:

@ExceptionHandler({MethodArgumentNotValidException.class})
  public void handleMethodArgumentNotValidException(
      MethodArgumentNotValidException manve, HttpServletResponse response) throws IOException {
    exceptionLog.error(manve.getMessage());
    Map<String, String> errors =
        manve
            .getBindingResult()
            .getFieldErrors()
            .stream()
            .collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
    String errorMessage = "...."
    if (!errors.isEmpty()) {
      ObjectMapper mapper = new ObjectMapper();
      errorMessage = mapper.writeValueAsString(errors);
    }

    response.sendError(400, errorMessage);
  }

【讨论】:

  • 在退出时间命中之前,我能够在响应拦截器中触摸响应 :),但扩展 DefaultErrorAttributes 看起来是更好、更不突兀的解决方案。谢谢!
猜你喜欢
  • 2018-11-08
  • 1970-01-01
  • 2022-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 2017-08-13
相关资源
最近更新 更多