#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)
Для получения дополнительной информации ознакомьтесь с Ограничениями элементов контейнера.