Spring validation возвращает длинные сообщения об ошибках, а не только настроенное сообщение

Spring validation возвращает длинное сообщение об ошибке вместо настроенного один раз.

Это часть кода в dto.

public class RequestDto implements Serializable {
    @NotNull(message="{id.required}")
    private Long id;

}

В контроллер добавлен @Valid для ввода.

@RequestMapping(value = ApiPath.PATH, method = RequestMethod.POST, produces = { "application/xml",
            "application/json" })
    public @ResponseBody ResultDecorator saveRequest(
            @Valid @RequestBody RequestDto msaDisabScreenRequestDto) throws Exception {

}

API возвращает следующую ошибку.

<message>Validation failed for argument at index 0 in method: public om.gov.moh.msa.framework.resolver.ResultDecorator om.controller.MaController.saveRequest(om..dto.RequestDto) throws java.lang.Exception, with 1 error(s): [Field error in object 'requestDto' on field 'id': rejected value [null]; codes [NotNull.requestDto.id,NotNull.id,NotNull.java.lang.Long,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [requestDto.id,id]; arguments []; default message [civilId]]; **default message [ID is required.]]** </message>

Здесь пользовательское сообщение присутствует в конце. (сообщение по умолчанию [ID требуется.)

Использование совета контроллера для глобального исключения, и я переопределяю handleMethodArgumentNotValid. Как я могу вернуть только пользовательское сообщение здесь?

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {



   /**
    * Spring validation related exception
    */
   @Override
   protected ResponseEntity<Object> handleMethodArgumentNotValid(
           MethodArgumentNotValidException ex,
           HttpHeaders headers,
           HttpStatus status,
           WebRequest request) {

       ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST);
       apiError.setMessage(ex.getMessage());
       return buildResponseEntity(apiError);
   }
}

4 ответа

Решение

Вы можете получить по умолчанию / пользовательское сообщение, как result.getFieldError("yourFieldName").getDefaultMessage()

Вы можете ловить сообщения об ошибках либо через метод контроллера, который должен выглядеть следующим образом

    @RequestMapping(value = ApiPath.PATH, method = RequestMethod.POST, produces = { "application/xml", "application/json" })
    public @ResponseBody ResultDecorator saveRequest(@Valid @RequestBody RequestDto msaDisabScreenRequestDto, BindingResult result) throws Exception {
        if(result.hasErrors()){
            String errorMessage = result.getFieldError("yourFieldName").getDefaultMessage();
        }
    }

Или через обработчик Global Exception

обновленный

    @Order(Ordered.HIGHEST_PRECEDENCE)
    @ControllerAdvice
    public class RestExceptionHandler extends ResponseEntityExceptionHandler {



       /**
        * Spring validation related exception
        */
       @Override
       protected ResponseEntity<Object> handleMethodArgumentNotValid(
               MethodArgumentNotValidException ex,
               HttpHeaders headers,
               HttpStatus status,
               WebRequest request) {

           //New Code
           BindingResult bindingResult = ex.getBindingResult();
           String errorMessage = result.getFieldError("yourFieldName").getDefaultMessage();
//---------------
           ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST);
           apiError.setMessage(errorMessage);
           return buildResponseEntity(apiError);
       }
    }

Спасибо Afridi, создал строковый буфер и добавил в него все сообщения об ошибках.

   /**
    * Spring validation related exception
    */
   @Override
   protected ResponseEntity<Object> handleMethodArgumentNotValid(
           MethodArgumentNotValidException ex,
           HttpHeaders headers,
           HttpStatus status,
           WebRequest request) {

       final StringBuffer errors = new StringBuffer();
       ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST);
       for (final FieldError error : ex.getBindingResult().getFieldErrors()) {
           errors.append("\n");
           errors.append(error.getField() + ": " + error.getDefaultMessage());
       }
       apiError.setMessage(errors.toString());
       return buildResponseEntity(apiError);
   }

Как сказал Африди в @ControllerAdvice можно сделать это также:

@ExceptionHandler(value = MethodArgumentNotValidException.class)
@SuppressWarnings("unchecked")
@ResponseBody
public Result methodArgumentNotValidExceptionHandler(HttpServletRequest req, HttpServletResponse response, MethodArgumentNotValidException e) throws IOException {
    String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();

    // todo return to your custom result
}

Есть два момента:

  • Исключительный класс MethodArgumentNotValidException
  • Первая ошибка getDefaultMessage() можете получить ваше собственное сообщение в Annotation

В WebFlux:

Ручка WebExchangeBindException для настройки сообщения об ошибке по умолчанию @Valid

      @ControllerAdvice
public class ValidationHandler {

    @ExceptionHandler(WebExchangeBindException.class)
    public ResponseEntity<List<String>> handleException(WebExchangeBindException e) {
        var errors = e.getBindingResult()
                .getAllErrors()
                .stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.toList());
        return ResponseEntity.badRequest().body(errors);
    }

}

Ссылка: https://www.vinsguru.com/spring-webflux-validation/

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