WebDataBinder and @MVC request param binding detect and introspect MultipartFile arrays as well (SPR-2784)

This commit is contained in:
Juergen Hoeller
2010-08-15 22:51:02 +00:00
parent 5b0448c609
commit 255d1ad434
8 changed files with 179 additions and 38 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -105,7 +105,7 @@ public class ServletRequestDataBinder extends WebDataBinder {
MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request);
if (request instanceof MultipartRequest) {
MultipartRequest multipartRequest = (MultipartRequest) request;
bindMultipartFiles(multipartRequest.getFileMap(), mpvs);
bindMultipart(multipartRequest.getMultiFileMap(), mpvs);
}
doBind(mpvs);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
package org.springframework.web.bind;
import java.lang.reflect.Array;
import java.util.List;
import java.util.Map;
import org.springframework.beans.MutablePropertyValues;
@@ -276,7 +277,10 @@ public class WebDataBinder extends DataBinder {
* @param mpvs the property values to be bound (can be modified)
* @see org.springframework.web.multipart.MultipartFile
* @see #setBindEmptyMultipartFiles
* @deprecated as of Spring 3.0, in favor of {@link #bindMultipart} which binds
* all multipart files, even if more than one sent for the same name
*/
@Deprecated
protected void bindMultipartFiles(Map<String, MultipartFile> multipartFiles, MutablePropertyValues mpvs) {
for (Map.Entry<String, MultipartFile> entry : multipartFiles.entrySet()) {
String key = entry.getKey();
@@ -287,4 +291,30 @@ public class WebDataBinder extends DataBinder {
}
}
/**
* Bind all multipart files contained in the given request, if any
* (in case of a multipart request).
* <p>Multipart files will only be added to the property values if they
* are not empty or if we're configured to bind empty multipart files too.
* @param multipartFiles Map of field name String to MultipartFile object
* @param mpvs the property values to be bound (can be modified)
* @see org.springframework.web.multipart.MultipartFile
* @see #setBindEmptyMultipartFiles
*/
protected void bindMultipart(Map<String, List<MultipartFile>> multipartFiles, MutablePropertyValues mpvs) {
for (Map.Entry<String, List<MultipartFile>> entry : multipartFiles.entrySet()) {
String key = entry.getKey();
List<MultipartFile> values = entry.getValue();
if (values.size() == 1) {
MultipartFile value = values.get(0);
if (isBindEmptyMultipartFiles() || !value.isEmpty()) {
mpvs.add(key, value);
}
}
else {
mpvs.add(key, values);
}
}
}
}

View File

@@ -78,6 +78,7 @@ import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.bind.support.WebRequestDataBinder;
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;
/**
@@ -153,7 +154,7 @@ public class HandlerMethodInvoker {
if (debug) {
logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
}
String attrName = AnnotationUtils.findAnnotation(attributeMethodToInvoke, ModelAttribute.class).value();
String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
continue;
}
@@ -381,7 +382,7 @@ public class HandlerMethodInvoker {
boolean debug = logger.isDebugEnabled();
for (Method initBinderMethod : initBinderMethods) {
Method methodToInvoke = BridgeMethodResolver.findBridgedMethod(initBinderMethod);
String[] targetNames = AnnotationUtils.findAnnotation(methodToInvoke, InitBinder.class).value();
String[] targetNames = AnnotationUtils.findAnnotation(initBinderMethod, InitBinder.class).value();
if (targetNames.length == 0 || Arrays.asList(targetNames).contains(attrName)) {
Object[] initBinderArgs =
resolveInitBinderArguments(handler, methodToInvoke, binder, webRequest);
@@ -481,15 +482,25 @@ public class HandlerMethodInvoker {
Object paramValue = null;
MultipartRequest multipartRequest = webRequest.getNativeRequest(MultipartRequest.class);
if (multipartRequest != null) {
paramValue = multipartRequest.getFile(paramName);
List<MultipartFile> files = multipartRequest.getFiles(paramName);
if (!files.isEmpty()) {
if (files.size() == 1 && !paramType.isArray() && !Collection.class.isAssignableFrom(paramType)) {
paramValue = files.get(0);
}
else {
paramValue = files;
}
}
}
if (paramValue == null) {
String[] paramValues = webRequest.getParameterValues(paramName);
if (paramValues != null && !paramType.isArray()) {
paramValue = (paramValues.length == 1 ? paramValues[0] : paramValues);
}
else {
paramValue = paramValues;
if (paramValues != null) {
if (paramValues.length == 1 && !paramType.isArray() && !Collection.class.isAssignableFrom(paramType)) {
paramValue = paramValues[0];
}
else {
paramValue = paramValues;
}
}
}
if (paramValue == null) {

View File

@@ -103,7 +103,7 @@ public class WebRequestDataBinder extends WebDataBinder {
if (request instanceof NativeWebRequest) {
MultipartRequest multipartRequest = ((NativeWebRequest) request).getNativeRequest(MultipartRequest.class);
if (multipartRequest != null) {
bindMultipartFiles(multipartRequest.getFileMap(), mpvs);
bindMultipart(multipartRequest.getMultiFileMap(), mpvs);
}
}
doBind(mpvs);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -64,7 +64,6 @@ public interface MultipartRequest {
* Return a {@link java.util.Map} of the multipart files contained in this request.
* @return a map containing the parameter names as keys, and the
* {@link MultipartFile} objects as values
* @see MultipartFile
*/
Map<String, MultipartFile> getFileMap();
@@ -72,7 +71,6 @@ public interface MultipartRequest {
* Return a {@link MultiValueMap} of the multipart files contained in this request.
* @return a map containing the parameter names as keys, and a list of
* {@link MultipartFile} objects as values
* @see MultipartFile
* @since 3.0
*/
MultiValueMap<String, MultipartFile> getMultiFileMap();