springMVC:为MultipartFilte配置了上传文件解析器,报错或不能使用

一、问题描述
为支持restful风格请求,并且应对可能上传文件的情况,需要在配置hiddenHttpMethodFilter过滤器之前配置MultipartFilter。目的是让MultipartFilter过滤器先将带文件上传的请求,进行解析。以便hiddenHttpMethodFilter可以取到”_method”参数,转化为相应的http动作。
既然multipartFilter要进行上传文件的解析,那么必然需要MutipartResolver,那么问题发生了!

二、报错:Unable to process parts as no multi-part configuration has been provided
配置如下

web.xml

<filter>
        <filter-name>MultipartFilter</filter-name>
        <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
        <init-param>
            <param-name>multipartResolverBeanName</param-name>
            <param-value>multipartResolver</param-value>
        </init-param>
</filter>

springmvc.xml DispatcherServlert的上下文文件 
我们使用了commons-fileupload-1.3.1.jar提供的CommonsMultipartResolver解析器

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
       <property name="maxUploadSize" value="20000000"/>
       <property name="defaultEncoding" value="utf-8"></property>
 </bean>

另外,还有一个multipartResolver需要介绍:
org.springframework.web.multipart.support.StandardServletMultipartResolver

CommonsMultipartResolver:使用commons Fileupload来处理multipart请求,使用时需导入jar包。
StandardServletMultipartResolver:是基于Servlet3.0来处理multipart请求的,所以不需要引用其他jar包,但是必须使用支持Servlet3.0的容器才可以.

原因:
如果你配置的multipartFilter的multipartResolver是CommonsMultipartResolver,即如上面springmvc.xml,
web.xml的配置,报这个错误的话,说明你配置的上传文件的解析器(CommonsMultipartResolver)根本,没有用到,而是使用这个上传文件的解析器(StandardServletMultipartResolver),而你又没有对这个解析器提供必要的配置信息,所以报错。

三、解决问题
1、解决报错
给StandardServletMultipartResolver提供配置信息即可,(注:为何这样配置,原因见https://blog.csdn.net/gao_zhennan/article/details/81327268)
web.xml

<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext-web.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>

<!--    StandardServletMultipartResolvershu属性配置  -->
    <multipart-config>
        <max-file-size>20848820</max-file-size>
        <max-request-size>418018841</max-request-size>
        <file-size-threshold>1048576</file-size-threshold>
    </multipart-config>
  </servlet>

至此、报错的问题已经解决。但是为什么我们配置的上传文件的解析器没有用到呢?说来话长,我们源码中见。

2,解决未使用我们自己配置的上传文件的解析器(CommonsMultipartResolver) 
MultipartFilter关键源码

public class MultipartFilter extends OncePerRequestFilter {
    public static final String DEFAULT_MULTIPART_RESOLVER_BEAN_NAME = "filterMultipartResolver";
    private String multipartResolverBeanName = DEFAULT_MULTIPART_RESOLVER_BEAN_NAME;
    private final MultipartResolver defaultMultipartResolver = new
      StandardServletMultipartResolver();

    //将web.xml文件中为multipartFilter设置的参数(init-param)的属性值(param-value),
    //通过调用set方法设置进来,此时multipartResolverBeanName=multipartResolver

    public void setMultipartResolverBeanName(String multipartResolverBeanName) {
        this.multipartResolverBeanName = multipartResolverBeanName;
    }

    protected String getMultipartResolverBeanName() {
        return this.multipartResolverBeanName;
    }

    protected MultipartResolver lookupMultipartResolver() {//关键方法:用来查找上传文件的解析器

        WebApplicationContext wac = WebApplicationContextUtils.
        getWebApplicationContext(getServletContext());
        // 1.WebApplicationContext 是spring的上下文对象,在ContextLoaderListener加载spring的配置文件后,将生成的对应的WebApplicationContext,先放在了web.xml的上下文对象中ServletContext

        String beanName = getMultipartResolverBeanName();
        // 2.上面有这个方法,返回值为this.multipartResolverBeanName,即"multipartResolver"
        if (wac != null && wac.containsBean(beanName)) {
            // 3.1只要监听器ContextLoaderListener,加载了spirng的配置文件wac 就不会是null,
            // 现在关键的是:ContextLoaderListener加载的配置文件中是否配置了这个bean(id="multipartResolver")
            return wac.getBean(beanName, MultipartResolver.class);
        }
        else {
            //3.2如过ContextLoaderListener加载的配置文件中没有这个bean,则与之
            //对应的WebApplicationContext对象中也不包含这个bean,
            //于是wac.containsBean(beanName) 为false。
            //返回默认的解析器"StandardServletMultipartResolver"
            return this.defaultMultipartResolver;
        }
    }

有点抽象,说的再多不如去做下。在前端页面发送了一个带文件上传控件的表单,看MutilFilter是否使用我配置的文件上传的解析器(CommonsMultipartResolver)。

wac.containsBean(beanName) beanName=”multipartResolver” 为false。说明你在spring的上下文中没有配置id=”multipartResolver”。奇怪了,我明明在springmvc.xml中配置了id=”multipartResolver”.为什么在spring对应的上下文对象中找不到呢?这里就要牵扯到新的概念了。

springmvc.xml是由DispatcherServlet加载的,然后生成了springmvc的上下文对象,称为子容器。 ContextLoaderListener加载的配置文件,生成的spring的上下文对象,称为父容器。 子容器可以使用父容器中定义的bean,反之则不行。 如上multipartResovler配置在springmvc.xnl中,即对应的bean在子容器中,而WebApplicationContext.containsBean()在父容器中是查找不到这个bean的
问题解决
1.新建一个applicationContext.xml(名字任意取),
2.将multipartResovler配置在其中。
3.重要的是要通过ContextLoaderListener来加载此文件,这样这个bean就在spring的容器里了,然后WebApplicationContext.containsBean()为true,就会使用你配置的解析器,而不是使用默认的了。
最后放张图

spring和spirngmvc父子容器介绍
(转发自https://blog.csdn.net/jml1437710575/article/details/52020936)
在百度中别人的帖子中看到一段应该是官方的原文解释,我摘抄过来并粗糙的直译一下:

Spring lets you define multiple contexts in a parent-child hierarchy.
spring允许你定义多个上下文在父子继承关系中

The applicationContext.xml defines the beans for the “root webapp context”, i.e. the context associated with the webapp.
applicationContext.xml文件是为了”根webapp应用上下文”定义bean, 也就是说它的上下文是和webapp想关联的

The spring-servlet.xml (or whatever else you call it) defines the beans for one servlet’s app context. There can be many of these in a webapp,
spring-servlet.xml文件(或是其他的你习惯的称呼)是为了一个servlet应用上下文呢定义bean. 在一个webapp中可以有多个此配置文件,

one per Spring servlet (e.g. spring1-servlet.xml for servlet spring1, spring2-servlet.xml for servlet spring2).
每一个spring的servlelt(例如: 名为spring1的servlet拥有配置文件spring1-servlet.xml, 名为spring2的servlet拥有配置文件spring2-servlet.xml).

Beans in spring-servlet.xml can reference beans in applicationContext.xml, but not vice versa.
在spring-servlet.xml中定义的bean可以直接引用在applicationContext.xml中定义的bean, 但是反过来不可以.

All Spring MVC controllers must go in the spring-servlet.xml context.
所有springmvc的Controller必须在spring-servlet.xml对应的上下文中运行.

In most simple cases, the applicationContext.xml context is unnecessary. It is generally used to contain beans that are shared between all servlets
在大多数简单的情况下, applicationContext.xml对应的上下文并不必须. 它通常用来包含那些bean用来在webapp中所有servlet之间共享.

in a webapp. If you only have one servlet, then there’s not really much point, unless you have a specific use for it.
如果你只有一个servlet, 那么实际没有什么必要定义applicationContext.xml, 除非你有特别应用.

本文转自:https://blog.csdn.net/gao_zhennan/article/details/81331218

原文地址:https://www.cnblogs.com/nizuimeiabc1/p/11031381.html

时间: 2024-08-24 16:11:59

springMVC:为MultipartFilte配置了上传文件解析器,报错或不能使用的相关文章

secureFX上传文件的时候报错,secureFX崩溃

SecureFX experienced a fatal error and must close.A crash dump file has been...... 打开注册表,HKEY_CURRENT_MACHINE->SOFTWARE->Vandyke中的secureCRT和secureFX中的license是secureCRT.secureFX的注册信息,不能删除,删除后需要重新注册. HKEY_CURRENT_USER->SOFTWARE->Vandyke中的secureC

Django配置用户上传文件夹和暴露后端文件夹资源

网站所用的静态文件我们都默认存放到static文件夹下,而用户上传的文件也是静态资源,我们需要找一个公共的地方专门存储用户上传的静态文件. 针对用户上传的不同文件,保存到指定的文件夹下. media配置专门用来指定用户上传的静态文件存放路径 1.配置文件中书写以下代码 # settings.py MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # 用户上传的文件就会保存到该文件夹下 # media是文件夹的名字,可以自定义,一般使用media作为名字 当

上传文件拦截器

1.FileUpload拦截器介绍 FileUpload拦截器Struts2预置的拦截器 见struts-default.xml第134行 FileUpload拦截器被默认拦截器栈defaultStack引用,即我们不需要做任何配置,即可使用该拦截器 见struts-default.xml第275行 FileUpload拦截器可以用于文件上传 2.FileUpload拦截器上传文件步骤 首先,FileUpload拦截器将表单中提交的文件,以临时文件的形式保存到服务器临时路劲下. 之后,FileU

dnmp(docker的lnmp)安装WordPress之后图片上传问题 问题:图片上传大小问题解决和 报错413 Request Entity Too Large

首先是提示超过图片尺寸和大小, 最后发现都是图片大小的问题, 需要修改php的最大上传size 修改之后查看php配置  已经生效  但是还是报错, 提示返回不是合法的json,  查看控制台, 报错是问题:413 Request Entity Too Large  发现是Nginx的配置, 有盖配置. dnmp环境  php配置  直接重新 docker-compose up --build  就可以生效 nginx 需要 停止 删除 重新build才可以, 注意, 停止删除容器, build

自己封装framworks上传到应用商店报错

参考链接: http://www.jianshu.com/p/60ac3ded34a0 http://ikennd.ac/blog/2015/02/stripping-unwanted-architectures-from-dynamic-libraries-in-xcode/ 原因:包含了模拟器内容 报错信息: ERROR ITMS-90087: "Unsupported Architectures. The executable for ***.app/Frameworks/SDK.fram

解决上传代码到GitHub报错Push rejected: Push to origin/master was rejected

最近在 push 代码到 github 时,IDEA报错 Push rejected: Push to origin/master was rejected 在网友找了一圈,发现都不是想要的答案 于是在命令行敲了一遍 git push,报错信息如下 remote: error: GH007: Your push would publish a private email address. 其实上面这个才是真正具体的错误原因,其实是你修改了设置里关于邮箱的一个选项 解决办法:在GitHub的你账号

git及github配置及上传文件到github地址

1.安装好git以后,我们配置git秘钥,首先输入下面的命令: 2.接着上述操作,一路回车按键.如图所示:生成了秘钥,, 如下图,就是秘钥了: 3.我们打开注册好的github地址.找到ssh选项,将秘钥添加到新的ssh秘钥. 4.git邮箱配置用户名:user.name 5.git邮箱配置邮箱账号: 6.github新建一个工程 7.创建成功后的页面. 8.git初始化仓库 使用git  init 初始化git仓库 9.通过vi 命令创建一个文件 10.添加文件到暂存区.git add .gi

上传文件的时候报长度超过限制长度

Server Error in '/' Application. Maximum request length exceeded. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated

【SpringMVC】使用SpringMVC进行上传文件!

写在前面: 之前在上传文件的时候,使用的是commons-file-upload这个插件,非常方便,能控制每个文件的大小,总共大小,缓存,以及支持多个文件的同时上传,但是写一次上传文件的后台代码量太大了,如图 如果有多个地方都要上传文件,每一次都要复制,粘贴一遍又一遍,实在是太麻烦,后台想到能不能把相同的代码都封装到一个方法,然后需要使用的时候再稍微改一下就行了,在封装的过程中,发现原来SpringMVC有自带的上传文件组件,遂用了一下,感觉多然很方面! 下面详细的说一下使用步骤! 1,准备好相