mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Improve SpringValidatorAdapter and MethodValidationAdapter performance
Closes gh-36621
(cherry picked from commit b8f1005897)
This commit is contained in:
+6
-1
@@ -553,7 +553,7 @@ public class MethodValidationAdapter implements MethodValidator {
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class ViolationMessageSourceResolvable extends DefaultMessageSourceResolvable {
|
||||
private class ViolationMessageSourceResolvable extends DefaultMessageSourceResolvable {
|
||||
|
||||
private final transient ConstraintViolation<Object> violation;
|
||||
|
||||
@@ -567,6 +567,11 @@ public class MethodValidationAdapter implements MethodValidator {
|
||||
public ConstraintViolation<Object> getViolation() {
|
||||
return this.violation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRenderDefaultMessage() {
|
||||
return validatorAdapter.get().requiresMessageFormat(this.violation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+22
-10
@@ -18,6 +18,7 @@ package org.springframework.validation.beanvalidation;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -64,7 +65,7 @@ import org.springframework.validation.SmartValidator;
|
||||
*/
|
||||
public class SpringValidatorAdapter implements SmartValidator, jakarta.validation.Validator {
|
||||
|
||||
private static final Set<String> internalAnnotationAttributes = Set.of("message", "groups", "payload");
|
||||
private static final Set<String> INTERNAL_ANNOTATION_ATTRIBUTES = Set.of("message", "groups", "payload");
|
||||
|
||||
|
||||
@Nullable
|
||||
@@ -145,10 +146,21 @@ public class SpringValidatorAdapter implements SmartValidator, jakarta.validatio
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
protected void processConstraintViolations(Set<ConstraintViolation<Object>> violations, Errors errors) {
|
||||
// Pre-identify binding failures (using getAllErrors to avoid intermediate list)
|
||||
Set<String> failedFields = new HashSet<>();
|
||||
if (errors.hasErrors()) {
|
||||
for (ObjectError error : errors.getAllErrors()) {
|
||||
if (error instanceof FieldError fieldError && fieldError.isBindingFailure()) {
|
||||
failedFields.add(fieldError.getField());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Turn the ConstraintViolations into Object/FieldErrors,
|
||||
// but only for fields where binding has been successful.
|
||||
for (ConstraintViolation<Object> violation : violations) {
|
||||
String field = determineField(violation);
|
||||
FieldError fieldError = errors.getFieldError(field);
|
||||
if (fieldError == null || !fieldError.isBindingFailure()) {
|
||||
if (!failedFields.contains(field)) {
|
||||
try {
|
||||
ConstraintDescriptor<?> cd = violation.getConstraintDescriptor();
|
||||
String errorCode = determineErrorCode(cd);
|
||||
@@ -159,14 +171,14 @@ public class SpringValidatorAdapter implements SmartValidator, jakarta.validatio
|
||||
String nestedField = bindingResult.getNestedPath() + field;
|
||||
if (nestedField.isEmpty()) {
|
||||
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode);
|
||||
ObjectError error = new ViolationObjectError(
|
||||
ObjectError error = new ValidationObjectError(
|
||||
errors.getObjectName(), errorCodes, errorArgs, violation, this);
|
||||
bindingResult.addError(error);
|
||||
}
|
||||
else {
|
||||
Object rejectedValue = getRejectedValue(field, violation, bindingResult);
|
||||
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode, field);
|
||||
FieldError error = new ViolationFieldError(errors.getObjectName(), nestedField,
|
||||
FieldError error = new ValidationFieldError(errors.getObjectName(), nestedField,
|
||||
rejectedValue, errorCodes, errorArgs, violation, this);
|
||||
bindingResult.addError(error);
|
||||
}
|
||||
@@ -261,7 +273,7 @@ public class SpringValidatorAdapter implements SmartValidator, jakarta.validatio
|
||||
// Using a TreeMap for alphabetical ordering of attribute names
|
||||
Map<String, Object> attributesToExpose = new TreeMap<>();
|
||||
descriptor.getAttributes().forEach((attributeName, attributeValue) -> {
|
||||
if (!internalAnnotationAttributes.contains(attributeName)) {
|
||||
if (!INTERNAL_ANNOTATION_ATTRIBUTES.contains(attributeName)) {
|
||||
if (attributeValue instanceof String str) {
|
||||
attributeValue = new ResolvableAttribute(str);
|
||||
}
|
||||
@@ -442,7 +454,7 @@ public class SpringValidatorAdapter implements SmartValidator, jakarta.validatio
|
||||
* Subclass of {@code ObjectError} with Spring-style default message rendering.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static class ViolationObjectError extends ObjectError implements Serializable {
|
||||
private static class ValidationObjectError extends ObjectError implements Serializable {
|
||||
|
||||
@Nullable
|
||||
private transient SpringValidatorAdapter adapter;
|
||||
@@ -450,7 +462,7 @@ public class SpringValidatorAdapter implements SmartValidator, jakarta.validatio
|
||||
@Nullable
|
||||
private transient ConstraintViolation<?> violation;
|
||||
|
||||
public ViolationObjectError(String objectName, String[] codes, Object[] arguments,
|
||||
public ValidationObjectError(String objectName, String[] codes, Object[] arguments,
|
||||
ConstraintViolation<?> violation, SpringValidatorAdapter adapter) {
|
||||
|
||||
super(objectName, codes, arguments, violation.getMessage());
|
||||
@@ -472,7 +484,7 @@ public class SpringValidatorAdapter implements SmartValidator, jakarta.validatio
|
||||
* Subclass of {@code FieldError} with Spring-style default message rendering.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static class ViolationFieldError extends FieldError implements Serializable {
|
||||
private static class ValidationFieldError extends FieldError implements Serializable {
|
||||
|
||||
@Nullable
|
||||
private transient SpringValidatorAdapter adapter;
|
||||
@@ -480,7 +492,7 @@ public class SpringValidatorAdapter implements SmartValidator, jakarta.validatio
|
||||
@Nullable
|
||||
private transient ConstraintViolation<?> violation;
|
||||
|
||||
public ViolationFieldError(String objectName, String field, @Nullable Object rejectedValue, String[] codes,
|
||||
public ValidationFieldError(String objectName, String field, @Nullable Object rejectedValue, String[] codes,
|
||||
Object[] arguments, ConstraintViolation<?> violation, SpringValidatorAdapter adapter) {
|
||||
|
||||
super(objectName, field, rejectedValue, false, codes, arguments, violation.getMessage());
|
||||
|
||||
Reference in New Issue
Block a user