Комментарии 10
А в спринге есть готовая поддержка для api фильтрации по многим параметрам с логическими функциями и операторами? Ну типа как в elastic search когда я хочу найти только автомобили или мотоциклы 2018-2019 года, только фирмы bmw и удовлетворяющие full-text запросу rusty junk:
/search?q=rusty junk&category=auto|moto&company=bmw&production_date>=01.01.2018&production_date<=2019
помнится когда прилетела такая задача, я подумал что это решается тремя строчками, и спринг все операторы распарсит. А спрингеры сказали что надо будет все ручками писать
Непонятно что тут хотели сказать:
Добавление аннотации @Validated в контроллер перед DTO, которую необходимо проверить при вызове данного end-point.
Чтобы вызвать проверки по аннотации Valid на RequestBody (или другой составной параметр метода), то не надо указывать Validated над контроллером, достаточно аннотации Valid над параметром. Это можно точно увидеть вот тут в документации. То есть Valid отработается самим Spring для контроллера. Для отработки других (NotNull, NotBlank) аннотаций надо уже указать Validated (или если это не контроллер). Также про это можно почитать у меня в канале телеграм раз, два. Или у меня в GitHub.
Также там есть в тексте "например", но его нет.
Так и описано было изначально не "над контроллером", а перед DTO, с примером ниже.
Разница @Validatedи @Validподробнее описана здесь.
"In Spring, we use JSR-303's @Valid annotation for method level validation. Moreover, we also use it to mark a member attribute for validation. However, this annotation doesn't support group validation.
Groups help to limit the constraints applied during validation. One particular use case is UI wizards. Here, in the first step, we may have a certain sub-group of fields. In the subsequent step, there may be another group belonging to the same bean. Hence we need to apply constraints on these limited fields in each step, but @Valid doesn't support this.
In this case, for group-level, we have to use Spring's @Validated, which is a variant of this JSR-303's @Valid. This is used at the method-level. And for marking member attributes, we continue to use the @Valid annotation."
По ссылкам, что вы отправили рассматривается только один случай применения — группы.
Есть другой пример использования, про который я писал в комментарии выше. По ссылкам там есть примеры этого использования. Я продублирую их тут.
Пример 1.
@Getter
// Без неё не будет происходить проверка, потому что не будет применен аспект.
@Validated
@ConstructorBinding
@AllArgsConstructor
@ConfigurationProperties("defaults")
public class DefaultsProperties {
@NotNull
private Author author;
@Getter
@AllArgsConstructor
public static class Author {
@NotBlank
private String name;
@NotBlank @Email @EmailDomains
private String email;
}
}
В документации.
Can also be used with method level validation, indicating that a specific class is supposed to be validated at the method level (acting as a pointcut for the corresponding validation interceptor), but also optionally specifying the validation groups for method-level validation in the annotated class. Applying this annotation at the method level allows for overriding the validation groups for a specific method but does not serve as a pointcut; a class-level annotation is nevertheless necessary to trigger method validation for a specific bean to begin with. Can also be used as a meta-annotation on a custom stereotype annotation or a custom group-specific validated annotation.
Выделение мое.
То есть аннотация Validated служит индикатором по которому к классу применяется обработчик валидация.
Пример 2.
@Service
// Также необходимо
@Validated
@RequiredArgsConstructor
public class CrudNewsService implements NewsService {
// ...
@Override
public News save(@Valid CreateNewsDto createNewsDto) {
News news = conversionService.convert(createNewsDto, News.class)
.applyDefaults(authorDefaults, defaultsAuthorFactory);
NewsModel newsModel = conversionService.convert(news, NewsModel.class);
NewsModel savedModel = newsRepository.save(newsModel);
return convertNewsModel(savedModel);
}
// ...
}
Также см. что я прикреплял выше:
Аннотация
@Valid
включает валидация на параметре. NOTE! Над классом не требуется указывать@Validated
, чтобы это работало для@Controller
классов. Чтобы валидация работала для других элементов контекста, добавьте над ним аннотацию@Validated
. Но чтобы работали аннотации@NotNull
,@NotBlank
и другие, надо ОБЯЗАТЕЛЬНО ставить аннотацию@Validated
. Также важно, что Spring MVC по-умолчанию обработает проверки, которые не требуют@Validated
на@Controller
Подробнее можно почитать по ссылкам, что я отправил.
А в этом есть вообще смысл?
Мое понимаени - поле уже и так не нулл и котлин не даст записать туда нулл еще до того как выполнится валидатор по аннотации
@field:NotNull
var startTime: LocalDateTime,
В случае с полями с nonnull типами (это не касается Int/Long), да, при вызове end-point со значением null исполнение свалится с Exception, но таким: HttpMessageNotReadableException
org.springframework.http.converter.: JSON parse error: Cannot construct instance of `com.epam.brn.dto.StudyHistoryDto`, problem: Parameter specified as non-null is null
Нам показалось разумнее сделать всю валидацию с помощью Spring однообразно для всех типов. Потому мы реализовали вышеописанный вариант.
Да.
@ElenaSpb подскажите, а почему было отдано предпочтение к описанию ошибок через файл в ресурсах? Если это валидация в DTO контроллера, то, как правило, на один метод - один DTO. Можно ведь явно указать руками сообщение
Да, Вы правы, можно сообщение и сразу непосредственно вставить в поле message, но в таком случае сообщения будут раскиданы по коду. Мы решили сделать централизованное место для сообщений ошибок, потому записываем в файл. Тут вопрос может не очень категоричный и можно делать по разному - кому как удобнее.
Spring валидация входных DTO в Kotlin. Краткая инструкция для backend-разработчика