Как проверить размер @RequestParam списка типов

#java #spring-boot #spring-web #spring-validator

#java #весенняя загрузка #spring-веб #spring-валидатор

Вопрос:

Я создаю REST API микросервиса Spring-BOOT, который ожидает @RequestParam тип List<String> . Как я могу проверить, что список содержит минимальное и максимальное количество значений?

До сих пор я пытался использовать @Size(min=1, max=2) который, как предполагается, также поддерживает коллекции ( javax.validation.constraints.Size ).

Я также безуспешно пытался добавить @Valid и BindingResult параметр вместе с @Size аннотацией.

Я бы предпочел использовать решение, аналогичное первому примеру с использованием @Size(min=1, max=2) , которое является более компактным и аккуратным. Это для весенней загрузки 2.1.2.RELEASE.

 @RestController
public class MyApi {

    @GetMapping(value = "/myApi", produces = { APPLICATION_JSON_VALUE })
    public ResponseEntity<List<MyObject>> getSomething(@Valid @RequestParam(value = "programEndTime", required = false) @Size(min = 1, max = 2) List<String> programEndTime, BindingResult result) {
        if (result.hasErrors()) {
            System.out.println("Error");
        } else {
            System.out.println("OK");
        }
    }
}
  

Я ожидаю, что будет достигнута System.out.println("Error") строка, но на самом деле она пропущена.

Комментарии:

1. Ваши ограничения являются логической ошибкой, @RequestParam(required=false) и @Size(min=1) все вместе не имеют смысла.

2. Уверен, что это может иметь смысл. С одной стороны, это не обязательный параметр, но с другой стороны, если он указан, он должен соответствовать ограничению размера.

Ответ №1:

Если вы используете проверку аргумента метода, вы должны пометить свой контроллер с помощью @Validated , как указано в документации:

Чтобы иметь право на проверку метода, управляемого Spring, все целевые классы должны быть снабжены @Validated аннотациями Spring. (При желании вы также можете объявить группы проверки для использования.) Подробности настройки с поставщиками Hibernate Validator и Bean Validation 1.1 см. в MethodValidationPostProcessor javadoc.

Это означает, что вы должны изменить свой код на:

 @Validated // Add this
@RestController
public class MyApi {
    // ...
}
  

После этого он выдаст ContraintViolationException , если проверка не соответствует.

Однако имейте в виду, поскольку у вас есть только @Size() аннотация, если вы не предоставите programEndTime , коллекция будет null , и она также будет действительной. Если вы этого не хотите, вам также следует добавить @NotNull аннотацию или удалить required = false значение из @RequestParam .

Вы не можете использовать BindingResult хотя для извлечения ошибок, поскольку это работает только для атрибутов модели или тел запроса. Что вы можете сделать, так это определить обработчик исключений для ConstraintViolationException :

 @ExceptionHandler(ConstraintViolationException.class)
public void handleConstraint(ConstraintViolationException ex) {
    System.out.println("Error");
}
  

Комментарии:

1. Спасибо. Однако, я боюсь, что это все еще не работает. Я добавил аннотацию «Validated» к классу, как было предложено. Требуется ли где-либо определять компонент MethodValidationPostProcessor? Или, может быть, я что-то еще упускаю?

2. @Nel Нет, это должно сработать. MethodValidationPostProcessor Компонент автоматически создается Spring boot. На самом деле я сам протестировал этот фрагмент кода, и проверка запускается, как только я посещаю http://localhost:8080/myApi?programEndTime или если я посещаю http://localhost:8080/myApi?programEndTime=Aamp;programEndTime=Bamp;programEndTime=C . Если у вас это не работает, пожалуйста, обязательно укажите ваши зависимости в вашем вопросе. Возможно, необходимые компоненты не создаются из-за отсутствия классов в вашем classpath.

3. Сначала это не сработало из-за компонента MethodValidationPostProcessor, который я добавил. После его удаления проверка прошла успешно.

Ответ №2:

Согласно Bean Validator 2.0, Hibernate Validator 6.x, вы можете использовать ограничения непосредственно для параметризованного типа.

 @GetMapping(path = "/myApi", produces = { APPLICATION_JSON_VALUE })
public ResponseEntity<List<MyObject>> getSomething(@RequestParam(value = "programEndTime", required = false) List<@Size(min = 1, max = 2) String> programEndTimes)
  

Для получения дополнительной информации ознакомьтесь с Ограничениями элементов контейнера.