Support method validation for Lists in WebMvc and WebFlux
Closes gh-31120
This commit is contained in:
@@ -18,6 +18,7 @@ package org.springframework.web.method;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -383,19 +384,25 @@ public class HandlerMethod extends AnnotatedMethod {
|
||||
*/
|
||||
private static class MethodValidationInitializer {
|
||||
|
||||
private static final Predicate<MergedAnnotation<? extends Annotation>> INPUT_PREDICATE =
|
||||
private static final Predicate<MergedAnnotation<? extends Annotation>> CONSTRAINT_PREDICATE =
|
||||
MergedAnnotationPredicates.typeIn("jakarta.validation.Constraint");
|
||||
|
||||
private static final Predicate<MergedAnnotation<? extends Annotation>> OUTPUT_PREDICATE =
|
||||
MergedAnnotationPredicates.typeIn("jakarta.validation.Valid", "jakarta.validation.Constraint");
|
||||
private static final Predicate<MergedAnnotation<? extends Annotation>> VALID_PREDICATE =
|
||||
MergedAnnotationPredicates.typeIn("jakarta.validation.Valid");
|
||||
|
||||
public static boolean checkArguments(Class<?> beanType, MethodParameter[] parameters) {
|
||||
if (AnnotationUtils.findAnnotation(beanType, Validated.class) == null) {
|
||||
for (MethodParameter parameter : parameters) {
|
||||
MergedAnnotations merged = MergedAnnotations.from(parameter.getParameterAnnotations());
|
||||
if (merged.stream().anyMatch(INPUT_PREDICATE)) {
|
||||
if (merged.stream().anyMatch(CONSTRAINT_PREDICATE)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
Class<?> type = parameter.getParameterType();
|
||||
if (merged.stream().anyMatch(VALID_PREDICATE) && List.class.isAssignableFrom(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -404,7 +411,7 @@ public class HandlerMethod extends AnnotatedMethod {
|
||||
public static boolean checkReturnValue(Class<?> beanType, Method method) {
|
||||
if (AnnotationUtils.findAnnotation(beanType, Validated.class) == null) {
|
||||
MergedAnnotations merged = MergedAnnotations.from(method, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
|
||||
return merged.stream().anyMatch(OUTPUT_PREDICATE);
|
||||
return merged.stream().anyMatch(CONSTRAINT_PREDICATE.or(VALID_PREDICATE));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -38,14 +38,14 @@ public class HandlerMethodTests {
|
||||
@Test
|
||||
void shouldValidateArgsWithConstraintsDirectlyOnClass() {
|
||||
Object target = new MyClass();
|
||||
testShouldValidateArguments(target, List.of("addIntValue", "addPersonAndIntValue"), true);
|
||||
testShouldValidateArguments(target, List.of("addIntValue", "addPersonAndIntValue", "addPersons"), true);
|
||||
testShouldValidateArguments(target, List.of("addPerson", "getPerson", "getIntValue", "addPersonNotValidated"), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldValidateArgsWithConstraintsOnInterface() {
|
||||
Object target = new MyInterfaceImpl();
|
||||
testShouldValidateArguments(target, List.of("addIntValue", "addPersonAndIntValue"), true);
|
||||
testShouldValidateArguments(target, List.of("addIntValue", "addPersonAndIntValue", "addPersons"), true);
|
||||
testShouldValidateArguments(target, List.of("addPerson", "addPersonNotValidated", "getPerson", "getIntValue"), false);
|
||||
}
|
||||
|
||||
@@ -110,6 +110,9 @@ public class HandlerMethodTests {
|
||||
public void addPersonAndIntValue(@Valid Person person, @Max(10) int value) {
|
||||
}
|
||||
|
||||
public void addPersons(@Valid List<Person> persons) {
|
||||
}
|
||||
|
||||
public void addPersonNotValidated(Person person) {
|
||||
}
|
||||
|
||||
@@ -134,6 +137,8 @@ public class HandlerMethodTests {
|
||||
|
||||
void addPersonAndIntValue(@Valid Person person, @Max(10) int value);
|
||||
|
||||
void addPersons(@Valid List<Person> persons);
|
||||
|
||||
void addPersonNotValidated(Person person);
|
||||
|
||||
@Valid
|
||||
@@ -159,6 +164,10 @@ public class HandlerMethodTests {
|
||||
public void addPersonAndIntValue(Person person, int value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPersons(List<Person> persons) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPersonNotValidated(Person person) {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user