Add BindingResultNameResolver option
See gh-29825
This commit is contained in:
@@ -85,6 +85,9 @@ public class MethodValidationAdapter {
|
||||
|
||||
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
|
||||
@Nullable
|
||||
private BindingResultNameResolver objectNameResolver;
|
||||
|
||||
|
||||
/**
|
||||
* Create an instance using a default JSR-303 validator underneath.
|
||||
@@ -157,6 +160,19 @@ public class MethodValidationAdapter {
|
||||
return this.parameterNameDiscoverer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a resolver for {@link BindingResult} method parameters to match
|
||||
* the behavior of the higher level programming model, e.g. how the name of
|
||||
* {@code @ModelAttribute} or {@code @RequestBody} is determined in Spring MVC.
|
||||
* <p>If this is not configured, then {@link #createBindingResult} will apply
|
||||
* default behavior to resolve the name to use.
|
||||
* behavior applies.
|
||||
* @param nameResolver the resolver to use
|
||||
*/
|
||||
public void setBindingResultNameResolver(BindingResultNameResolver nameResolver) {
|
||||
this.objectNameResolver = nameResolver;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use this method determine the validation groups to pass into
|
||||
@@ -307,6 +323,10 @@ public class MethodValidationAdapter {
|
||||
|
||||
/**
|
||||
* Select an object name and create a {@link BindingResult} for the argument.
|
||||
* You can configure a {@link #setBindingResultNameResolver(BindingResultNameResolver)
|
||||
* bindingResultNameResolver} to determine in a way that matches the specific
|
||||
* programming model, e.g. {@code @ModelAttribute} or {@code @RequestBody} arguments
|
||||
* in Spring MVC.
|
||||
* <p>By default, the name is based on the parameter name, or for a return type on
|
||||
* {@link Conventions#getVariableNameForReturnType(Method, Class, Object)}.
|
||||
* <p>If a name cannot be determined for any reason, e.g. a return value with
|
||||
@@ -316,22 +336,30 @@ public class MethodValidationAdapter {
|
||||
* @return the determined name
|
||||
*/
|
||||
private BindingResult createBindingResult(MethodParameter parameter, @Nullable Object argument) {
|
||||
// TODO: allow external customization via Function (e.g. from @ModelAttribute + Conventions based on type)
|
||||
String objectName = parameter.getParameterName();
|
||||
int index = parameter.getParameterIndex();
|
||||
if (index == -1) {
|
||||
try {
|
||||
Method method = parameter.getMethod();
|
||||
if (method != null) {
|
||||
Class<?> resolvedType = GenericTypeResolver.resolveReturnType(method, parameter.getContainingClass());
|
||||
objectName = Conventions.getVariableNameForReturnType(method, resolvedType, argument);
|
||||
}
|
||||
String objectName = null;
|
||||
if (this.objectNameResolver != null) {
|
||||
objectName = this.objectNameResolver.resolveName(parameter, argument);
|
||||
}
|
||||
else {
|
||||
if (parameter.getParameterIndex() != -1) {
|
||||
objectName = parameter.getParameterName();
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// insufficient type information
|
||||
else {
|
||||
try {
|
||||
Method method = parameter.getMethod();
|
||||
if (method != null) {
|
||||
Class<?> containingClass = parameter.getContainingClass();
|
||||
Class<?> resolvedType = GenericTypeResolver.resolveReturnType(method, containingClass);
|
||||
objectName = Conventions.getVariableNameForReturnType(method, resolvedType, argument);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// insufficient type information
|
||||
}
|
||||
}
|
||||
}
|
||||
if (objectName == null) {
|
||||
int index = parameter.getParameterIndex();
|
||||
objectName = (parameter.getExecutable().getName() + (index != -1 ? ".arg" + index : ""));
|
||||
}
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(argument, objectName);
|
||||
@@ -340,6 +368,22 @@ public class MethodValidationAdapter {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Contract to determine the object name of an {@code @Valid} method parameter.
|
||||
*/
|
||||
public interface BindingResultNameResolver {
|
||||
|
||||
/**
|
||||
* Determine the name for the given method parameter.
|
||||
* @param parameter the method parameter
|
||||
* @param value the argument or return value
|
||||
* @return the name to use
|
||||
*/
|
||||
String resolveName(MethodParameter parameter, @Nullable Object value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds a validation result for a value method parameter with constraints
|
||||
* declared directly on it.
|
||||
|
||||
Reference in New Issue
Block a user