首页 > 解决方案 > 在 REST API 中自定义/修补 400 响应

问题描述

我已经使用 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 中还有一些元素,比如代码和东西。也试图接近那些。

标签: javaspringswagger

解决方案


默认情况下,所有错误消息都是内置的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);
  }

推荐阅读