为什么Spring MVC将空对象插入应该是空列表?

时间:2014-03-13 21:15:34

标签: java spring spring-mvc

我上传了多个文件。当我实际选择要上传的文件时,这很好用;他们很好地进入他们的列表,但是当我点击上传而不选择文件时,我得到一个包含空文件的List。我的验证器正在检查此List的大小是否为0,因此它会超过它。

是的,我可以解决它只是检查一个空文件,是的我可以在没有选择文件时禁用上传按钮,但我想知道为什么Spring会这样做以及可能如何阻止它执行此操作

这是jsp:

<form:form commandName="documentsBean" enctype="multipart/form-data">
    <input type="hidden" name="submittedFormAction" value="attachDocumentSave"/>
    <input type="file" name="files" id="attachFiles" multiple/>
    <button type="submit">Attach</button>
</form:form>

豆子,这里没什么好看的:

public class DocumentsBean
{
    private List<MultipartFile> files;
    public List<MultipartFile> getFiles(){
        return files;
    }
    public void setFiles(List<MultipartFile> files){
        this.files = files;
    }
}

控制器:

@RequestMapping( method = RequestMethod.POST, params = { "submittedFormAction=attachDocumentSave" })
public ModelAndView attachDocumentSave(HttpServletRequest request, @ModelAttribute("documentsBean") DocumentsBean documentsBean, BindingResult errors) throws Exception
{
    // At this point documentsBean.files is an ArrayList<E> with size = 1
}

当我深入查看documentsBean.files时,我看到elementData[0]CommonsMultipartFile,其fileName是一个空字符串,其大小为0.

发生了什么事?

1 个答案:

答案 0 :(得分:5)

这是您的解决方案。解释如下。

添加设置以下属性的@InitBinder方法。理想情况下,您可以将其添加到@ControllerAdvice类,但具有相应@RequestMapping方法的控制器也可以。

@InitBinder
public void init(WebDataBinder binder) {
    binder.setBindEmptyMultipartFiles(false);
}

您还需要像这样更改DocumentsBean课程

private List<MultipartFile> files = Arrays.asList();

因此该字段不是null

Spring使用ServletModelAttributeMethodProcessor生成@ModelAttribute带注释参数的参数,例如你的

@ModelAttribute("documentsBean") DocumentsBean documentsBean

这个HandlerMethodArgumentResolver使用请求(及其表单参数)通过将参数绑定到实例类来生成参数类型的实例。 实例字段。如果它检测到请求的内容类型为multipart/form-data,则会执行特殊绑定。

此绑定在WebDataBinder#bindMultipart(..)中完成。它检索由MultipartFile创建的所有MulitpartResolver个对象。如果只有一个,它会检查两件事。

if (isBindEmptyMultipartFiles() || !value.isEmpty()) {
    mpvs.add(key, value);
}

第一个方法调用

  

返回[s]是否绑定空MultipartFile个参数。

,第二个检查MultipartFile是否有任何正文内容。如果您在未选择文件的情况下提交表单(或者您选择了空文件AFAIK),则不会。

如果其中任何一个表达式解析为true,那么Spring将为您的处理程序方法提供此空MultipartFile持有者。否则,它将不会绑定该字段,这就是您想要一个默认值的原因(因此它不会保留null

private List<MultipartFile> files = Arrays.asList();

查看WebDataBinder#setBindEmptyMultipartFiles(boolean)的javadoc状态

  

设置是否绑定空的MultipartFile参数。默认为“true”。

     

如果要在何时保留已绑定的MultipartFile,请将其关闭   用户重新提交表单而不选择其他文件。其他,   已绑定的MultipartFile将替换为空   MultipartFile持有人。

这是您应在上面显示的false方法中设置为@InitBinder的属性。