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

Zoo*_*ook 5 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>
Run Code Online (Sandbox Code Playgroud)

豆子,没什么特别的:

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

控制器:

@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
}
Run Code Online (Sandbox Code Playgroud)

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

到底是怎么回事?

Sot*_*lis 5

这是你的解决方案.解释如下.

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

@InitBinder
public void init(WebDataBinder binder) {
    binder.setBindEmptyMultipartFiles(false);
}
Run Code Online (Sandbox Code Playgroud)

你还需要DocumentsBean像这样改变你的课程

private List<MultipartFile> files = Arrays.asList();
Run Code Online (Sandbox Code Playgroud)

所以这个领域不是null.

Spring使用a ServletModelAttributeMethodProcessor@ModelAttribute像你这样的带注释的参数生成一个参数

@ModelAttribute("documentsBean") DocumentsBean documentsBean
Run Code Online (Sandbox Code Playgroud)

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

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

if (isBindEmptyMultipartFiles() || !value.isEmpty()) {
    mpvs.add(key, value);
}
Run Code Online (Sandbox Code Playgroud)

第一个方法调用

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

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

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

private List<MultipartFile> files = Arrays.asList();
Run Code Online (Sandbox Code Playgroud)

看看WebDataBinder#setBindEmptyMultipartFiles(boolean)哪些状态的javadoc

设置是否绑定空的MultipartFile参数.默认为"true".

如果要在用户重新提交表单时保留已绑定的MultipartFile而不选择其他文件,请将其关闭.否则,已经绑定的MultipartFile将被空的MultipartFile持有者替换.

这是您应该false@InitBinder上面显示的方法中设置的属性.