Exclude Part and MultipartFile from nested constructor binding
Closes gh-31669
This commit is contained in:
@@ -948,7 +948,7 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
Class<?> paramType = paramTypes[i];
|
||||
Object value = valueResolver.resolveValue(paramPath, paramType);
|
||||
|
||||
if (value == null && shouldCreateObject(param)) {
|
||||
if (value == null && shouldConstructArgument(param)) {
|
||||
ResolvableType type = ResolvableType.forMethodParameter(param);
|
||||
args[i] = createObject(type, paramPath + ".", valueResolver);
|
||||
}
|
||||
@@ -1008,7 +1008,14 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
return (isOptional && !nestedPath.isEmpty() ? Optional.ofNullable(result) : result);
|
||||
}
|
||||
|
||||
private static boolean shouldCreateObject(MethodParameter param) {
|
||||
/**
|
||||
* Whether to instantiate the constructor argument of the given type,
|
||||
* matching its own constructor arguments to bind values.
|
||||
* <p>By default, simple value types, maps, collections, and arrays are
|
||||
* excluded from nested constructor binding initialization.
|
||||
* @since 6.1.2
|
||||
*/
|
||||
protected boolean shouldConstructArgument(MethodParameter param) {
|
||||
Class<?> type = param.nestedIfOptional().getNestedParameterType();
|
||||
return !(BeanUtils.isSimpleValueType(type) ||
|
||||
Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type) || type.isArray());
|
||||
|
||||
@@ -24,6 +24,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.Part;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -120,6 +121,13 @@ public class ServletRequestDataBinder extends WebDataBinder {
|
||||
return new ServletRequestValueResolver(request, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldConstructArgument(MethodParameter param) {
|
||||
Class<?> type = param.nestedIfOptional().getNestedParameterType();
|
||||
return (super.shouldConstructArgument(param) &&
|
||||
!MultipartFile.class.isAssignableFrom(type) && !Part.class.isAssignableFrom(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the parameters of the given request to this binder's target,
|
||||
* also binding multipart files in case of a multipart request.
|
||||
|
||||
@@ -18,8 +18,10 @@ package org.springframework.web.bind.support;
|
||||
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.Part;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -30,6 +32,7 @@ import org.springframework.web.bind.ServletRequestDataBinder;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartRequest;
|
||||
import org.springframework.web.multipart.support.StandardServletPartUtils;
|
||||
|
||||
@@ -118,6 +121,12 @@ public class WebRequestDataBinder extends WebDataBinder {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldConstructArgument(MethodParameter param) {
|
||||
Class<?> type = param.nestedIfOptional().getNestedParameterType();
|
||||
return (super.shouldConstructArgument(param) &&
|
||||
!MultipartFile.class.isAssignableFrom(type) && !Part.class.isAssignableFrom(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the parameters of the given request to this binder's target,
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
@@ -41,6 +42,7 @@ import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static java.lang.annotation.ElementType.CONSTRUCTOR;
|
||||
@@ -298,6 +300,7 @@ public class ModelAttributeMethodProcessorTests {
|
||||
Object resolved = this.processor.resolveArgument(this.beanWithConstructorArgs, this.container, requestWithParam, factory);
|
||||
assertThat(resolved).isInstanceOf(TestBeanWithConstructorArgs.class);
|
||||
assertThat(((TestBeanWithConstructorArgs) resolved).listOfStrings).containsExactly("1", "2");
|
||||
assertThat(((TestBeanWithConstructorArgs) resolved).file).isNull();
|
||||
}
|
||||
|
||||
private void testGetAttributeFromModel(String expectedAttrName, MethodParameter param) throws Exception {
|
||||
@@ -375,8 +378,11 @@ public class ModelAttributeMethodProcessorTests {
|
||||
|
||||
final List<String> listOfStrings;
|
||||
|
||||
public TestBeanWithConstructorArgs(List<String> listOfStrings) {
|
||||
final MultipartFile file;
|
||||
|
||||
public TestBeanWithConstructorArgs(List<String> listOfStrings, @Nullable MultipartFile file) {
|
||||
this.listOfStrings = listOfStrings;
|
||||
this.file = file;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user