在 Spring MVC 上使用 Servlet 3.0 的 MultipartConfig [英] MultipartConfig with Servlet 3.0 on Spring MVC

查看:38
本文介绍了在 Spring MVC 上使用 Servlet 3.0 的 MultipartConfig的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将多部分配置添加到使用带有 RequestMapping 注释的方法的控制器的 spring mvc 应用程序中?

How do I add in multipart configuration to a spring mvc app which uses controllers with methods annotated with RequestMapping?

背景:

我想启用 csrf 保护,因此在我的 spring 配置中添加了 security:csrf 标签.我有一个控制器类,其中包含一个用 RequestMapping 注释的方法,用于上传文件.我也跟着 警告说明 围绕多部分,我在安全过滤器上方添加了多部分过滤器.当我在添加 csrf 标签后尝试上传文件时,我在缺少 getParts() 方法时遇到异常.一个快速的谷歌强调这是由于使用了基于 servlet 2.5 规范的码头版本.我将 jetty-maven-plugin 升级到 8.1.14.v20131031 并再次尝试上传.结果:

I want to enable csrf protection and so have added the security:csrf tag in my spring config. I have a controller class with a method annotated with RequestMapping used for uploading files. I also followed the caveat instructions around multipart whereby I added the multipart filter above the security filter. When I tried to upload a file after adding the csrf tag I got an exception around a missing getParts() method. A quick google highlighted this was due to using a version of jetty which was based on the servlet 2.5 spec. I upgraded jetty-maven-plugin to 8.1.14.v20131031 and tried uploading again. Resulting in:

org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: No multipart config for servlet
        at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:68)
        at org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:58)
        at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:110)

我应该把 xml 设置的多部分配置放在哪里?所有文档都说要在 web.xml 中特定 servlet 的 servlet 标记中添加 multipart-config.不过,我的应用程序只有一个 servlet.所以我添加了它,但我仍然遇到同样的问题.

Where do I put the multipart configuration for xml setup? All documentation says to add the multipart-config in the servlet tag for the specific servlet in web.xml. There is only a single servlet for my application though. So I added it to that and still I get the same issue.

<servlet>
    <servlet-name>SpringDispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <multipart-config>
        <location>/tmp</location>
        <max-file-size>20848820</max-file-size>
        <max-request-size>418018841</max-request-size>
        <file-size-threshold>1048576</file-size-threshold>
    </multipart-config>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/servlet-context.xml
        </param-value>
    </init-param>
    <load-on-startup>10</load-on-startup>
</servlet>

我还更新了 web.xml 顶部的架构位置以指向 servlet 规范的 3.0 版,该规范来自 http://www.mkyong.com/web-development/the-web-xml-deployment-descriptor-examples/.

I also updated the schema location at the top of web.xml to point at version 3.0 of the servlet spec, sourced from http://www.mkyong.com/web-development/the-web-xml-deployment-descriptor-examples/.

有什么帮助吗?

为 Rob 添加了以下内容:

added the following riles for Rob:

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/spring/webapp.xml</param-value>
    </context-param>

    <context-param>
        <param-name>spring.profiles.default</param-name>
        <param-value>OracleDB,common</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <listener>
        <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>SpringDispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <multipart-config>
            <location>/tmp</location>
            <max-file-size>20848820</max-file-size>
            <max-request-size>418018841</max-request-size>
            <file-size-threshold>1048576</file-size-threshold>
        </multipart-config>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/servlet-context.xml
            </param-value>
        </init-param>
        <load-on-startup>10</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringDispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>MultipartFilter</filter-name>
        <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>MultipartFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy
        </filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>sitemesh</filter-name>
        <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>sitemesh</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>XSS</filter-name>
        <filter-class>com.mycompany.CrossScriptingFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>XSS</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <session-config>
        <session-timeout>10</session-timeout>
    </session-config>

    <resource-ref>
        <description>Core Datasource</description>
        <res-ref-name>jdbc/coreDataSource</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>

    <resource-ref>
        <description>Location Datasource</description>
        <res-ref-name>jdbc/locationDataSource</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>

    <error-page>
        <!-- Missing login -->
        <error-code>401</error-code>
        <location>/WEB-INF/views/errorPage.jsp</location>
    </error-page>
    <error-page>
        <!-- Forbidden directory listing -->
        <error-code>403</error-code>
        <location>/WEB-INF/views/errorPage.jsp</location>
    </error-page>
    <error-page>
        <!-- Missing resource -->
        <error-code>404</error-code>
        <location>/WEB-INF/views/errorPageNotFound.jsp</location>
    </error-page>
    <error-page>
        <!-- Uncaught exception -->
        <error-code>500</error-code>
        <location>/WEB-INF/views/errorPage.jsp</location>
    </error-page>
    <error-page>
        <!-- Unsupported servlet method -->
        <error-code>503</error-code>
        <location>/WEB-INF/views/errorPage.jsp</location>
    </error-page>

</web-app>

servlet-context.xml

servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <mvc:annotation-driven />

    <mvc:resources mapping="/resources/**" location="/resources/" />
    <mvc:resources mapping="/images/**" location="file:${fileSystemStore.fileSystemStorageLocation}"/>

    <context:component-scan base-package="com.mycompany.console.*" />

    <mvc:interceptors>
        <bean class="com.mycompany.security.ChangePasswordInterceptor" />
    </mvc:interceptors>

    <security:global-method-security
        secured-annotations="enabled" jsr250-annotations="enabled"
        pre-post-annotations="enabled" proxy-target-class="true" />

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
        <property name="contentType" value="text/html;charset=UTF-8" />
    </bean>

    <bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="100000000"/>
    </bean>

    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>classpath:language</value>
                <value>classpath:language_additions</value>
                <value>classpath:formats</value>
            </list>
        </property>
        <property name="defaultEncoding" value="UTF-8" />
    </bean>

    <bean id="localeResolver" class="com.mycompany.locale.SessionLocaleResolver"/>

</beans>

推荐答案

我相信您遇到了与 SPR-11373.具体来说,servlet 规范并不清楚在过滤器中执行多部分解析时应该发生什么.

I believe you are having issues related to SPR-11373. Specifically, the servlet specification is not clear on what should happen when performing multipart resolution within a Filter.

您是否尝试过使用 commons-fileupload 代替?这可能是您最好的选择.首先添加如下依赖:

Have you tried using commons-fileupload instead? This is likely your best option. First add the following dependency:

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.2.2</version>
</dependency>

接下来确保您的根应用程序上下文中有以下 bean 定义.

Next ensure you have the following bean definition in your root application context.

<bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000000"/>
</bean>

您可以找到一个完整的工作示例,其中包含 commons-upload(首选此解决方案)和使用 allowCasualMultipartParsing SEC-2471

You can find a complete working example with both commons-upload (prefer this solution) and using tomcat using allowCasualMultipartParsing on SEC-2471

这篇关于在 Spring MVC 上使用 Servlet 3.0 的 MultipartConfig的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆