Сообщение об исключении из-за отсутствия параметра метода @RequestBody

Во-первых, если у вас есть какие-либо идеи или решения, спасибо вам представить здесь. Я использую @RequestBody на одном из моих контроллеров для обязательного параметра, мне нужен какой-то полезный способ сказать, какой параметр отсутствовал, если его там нет. Когда пропущены некоторые параметры, генерируется исключение NullPointerException, поэтому я создаю новое исключение для экземпляра этого нулевого исключения (см. Http emun и 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 класс:

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",
}

Я ожидаю, что в подробностях появится сообщение "Требуется содержание тела запроса: канал":

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

Как я мог это сделать? Спасибо, парни!

1 ответ

Решение

Лучшим подходом, если вы можете сделать это, вероятно, будет использование JSR 303 Validation, которая, вероятно, включена в ваши существующие зависимости Spring, если вы используете последние версии.

Здесь есть хорошее, хотя и довольно простое учебное пособие: https://www.mkyong.com/spring-mvc/spring-rest-api-validation/ и многое другое в Интернете с более подробной информацией.

Официальные документы Spring по этому вопросу находятся здесь: https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/

Вам нужно всего лишь внести изменения в несколько классов, и вы можете удалить большую часть обработки исключений, в зависимости от того, какой уровень контроля вы хотите получить, или от того, насколько вы готовы использовать стандартные настройки 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 возражать и отвечать соответственно. Это может означать отправку определенного ответа от контроллера или выдачу исключения для обработки вашим существующим механизмом обработки исключений.

Другие вопросы по тегам