缺少@RequestBody 方法参数的异常消息

exception message for missing @RequestBody method parameter

首先,如果您有任何想法或解决方案,谢谢您在这里提出。 我在我的一个控制器上使用 @RequestBody 作为必需参数,我需要一些有用的方法来说明缺少哪个参数(如果不存在)。 当缺少一些参数时,它会抛出 NullPointerException,所以我为这个 null 异常的实例创建了一个新的异常(请参阅 httpemun 和 httphandler) 这些是提到这个问题的主要代码。

我的控制器:

public ResponseEntity<?> createOrder(@RequestBody Cart cart) throws Exception {
  // ......
}

我的实体购物车:

public class Cart{
      private String channel
      private String cartId;
      private String status;
      private String currency;

      getters...
      setters...

    }

我的 Http emun class:

public enum HttpStatusEnum {
    CRE_CART_INCOMPLETE_BODY(400,"E001","Incomplete request body","");
    private HttpStatusEnum(int statusCode, String code,
                           String message, String detail) {
        this.statusCode = statusCode;
        this.code = code;
        this.message = message;
        this.detail = detail;
    }

    private final int statusCode;
    private final String code;
    private final String message;
    private String detail;

    public int getStatusCode() {
        return statusCode;
    }

    public String getCode() {
        return code;
    }
    public String getMessage() {
        return message;
    }
    public void setDetail(String detail) {      
        this.detail = detail;
    }

    public String getDetail() {     
        if(detail.isEmpty()) {
            return message;
        }else {
            return detail;
        }
    }
}

我也有一个异常句柄

@ControllerAdvice
public class GlobalExceptionHandler {
    private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseEntity<Object> defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
  if(e instanceof NullPointerException)
    {if(req.getRequestURL().toString().contains(HttpSourceEnum.CART.toString()) && req.getMethod().equals(RequestMethod.POST.toString())){   
            errorBodyVo.setMessage(HttpStatusEnum.CRE_CART_INCOMPLETE_BODY.getMessage());
            errorBodyVo.setDetails(HttpStatusEnum.CRE_CART_INCOMPLETE_BODY.getDetail());  
            errorBodyVo.setCode(HttpStatusEnum.CRE_CART_INCOMPLETE_BODY.getCode());         
        }else {        
            errorBodyVo.setMessage(HttpStatusEnum.COMMON_MISSING_FIELD.getMessage());
            errorBodyVo.setDetails(HttpStatusEnum.COMMON_MISSING_FIELD.getDetail());  
            errorBodyVo.setCode(HttpStatusEnum.COMMON_MISSING_FIELD.getCode());
        }    
        httpStatus = HttpStatus.BAD_REQUEST;
    }
}

现在, 我的 API 请求是:

{
  "channel": "XX",
  "cartId": "109",
  "status": "1",
}

我收到如下 API 回复:

{
    "error": {
        "code": "E001",
        "message": "Incomplete request body",
        "details": ""
    }
}

但它与我的预期不符。 如果我的请求中缺少频道,如下所示:

{
  "cartId": "109",
  "status": "1",
}

我希望在细节中显示"Required request body content is missing: Channel":

{
    "error": {
        "code": "E001",
        "message": "Incomplete request body",
        "details": "Required request body content is missing: Channel"
    }
}

我该怎么做?谢谢大家!

一个更好的方法,如果你能做到的话,可能是使用 JSR 303 验证,它可能包含在你现有的 Spring 依赖项中,假设你使用的是最新版本。

这里有一个很好但很简单的教程:https://www.mkyong.com/spring-mvc/spring-rest-api-validation/ 以及更多在线教程,其中包含更多详细信息。

有关该主题的官方 Spring 文档位于:https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#validation-beanvalidation

您应该只需要对几个 class 进行更改,并且可能会删除很多异常处理,具体取决于您想要多少控制权,或者您愿意去多少使用 Spring 的默认值。不过,您需要进行的基本更改是:

要告诉 Spring 需要什么验证,您可以在 Cart class 中添加一个或多个注释,例如,如果您要确保指定频道,你可以这样做:

public class Cart{
  @NotNull
  private String channel
  private String cartId;
  private String status;
  private String currency;

然后,要指示 Spring 在将 Cart 对象传递给控制器​​之前对其进行验证,您需要向控制器方法签名添加 @Valid 注释:

public ResponseEntity<?> createOrder(@Valid @RequestBody Cart cart) throws Exception {

最后,再次修改 createOrder 签名以接受 Errors 对象:

public ResponseEntity<?> createOrder(@Valid @RequestBody Cart cart, Errors errors) throws Exception {

createOrder 方法中,您可以查询 Errors 对象并做出相应的响应。这可能意味着从控制器发送特定响应或抛出异常以由您现有的异常处理机制处理。