SpringMVC上传文件的五种配置

我们知道web上传文件form表单要加enctype=“multipart/form-data”,而SpringMVC提供了MultipartResolver接口来让实现文件流解析。而SpringMVC提供了两种解析器

CommonsMultipartResolver

我们点开这个文件解析器的源码发现继承了CommonsFileUploadSupport,而再点开这类support抽象类,发现里面是对fileupload的封装,使用过struts框架的同学肯定知道struts时有smartupload和fileUpload两个工具包。所以使用CommonsMultipartResolver实际就是用fileupload,这里要引用
commons-fileupload、commons-io这两个工具包。然后这里有两种配置:
1.spring-mvc.xml定义一个类型为CommonsMultipartResolver、id为multipartResolver的bean ,设置文件上传的最大字节数

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
		<property name="maxUploadSize" value="${web.maxUploadSize}" />  
</bean>

有的同学会问,这样为什么就可以了呢,用其他id名称可以不,这里明确说如果这里配置明确不可以,我们知道通常我们要在web.xml里引用SpringMVC的默认servlet,类似下面

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

其中servlet-name随便定义,spring-mvc.xml文件名随便定义,我们点开DispatcherServlet源码发现如下有MultipartResolver初始化,

	/**
	 * Initialize the MultipartResolver used by this class.
	 * <p>If no bean is defined with the given name in the BeanFactory for this namespace,
	 * no multipart handling is provided.
	 */
	private void initMultipartResolver(ApplicationContext context) {
		try {
			this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			// Default is no multipart resolver.
			this.multipartResolver = null;
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate MultipartResolver with name '" + MULTIPART_RESOLVER_BEAN_NAME +
						"': no multipart request handling provided");
			}
		}
	}
public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";

这里会到上下文中找id为multipartResolver的bean
2. web.xml定义一个MultipartFilter,我们点击MultipartResolver这个接口,发现有个MultipartFilter过滤器引用了他,而该过滤器在springmvc默认配置里还没引用,我们点击源码

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

   public MultipartFilter() {
   }

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

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

   protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
       MultipartResolver multipartResolver = this.lookupMultipartResolver(request);
       HttpServletRequest processedRequest = request;
       if (multipartResolver.isMultipart(request)) {
           if (this.logger.isDebugEnabled()) {
               this.logger.debug("Resolving multipart request [" + request.getRequestURI() + "] with MultipartFilter");
           }

           processedRequest = multipartResolver.resolveMultipart(request);
       } else if (this.logger.isDebugEnabled()) {
           this.logger.debug("Request [" + request.getRequestURI() + "] is not a multipart request");
       }

       try {
           filterChain.doFilter((ServletRequest)processedRequest, response);
       } finally {
           if (processedRequest instanceof MultipartHttpServletRequest) {
               multipartResolver.cleanupMultipart((MultipartHttpServletRequest)processedRequest);
           }

       }

   }

   protected MultipartResolver lookupMultipartResolver(HttpServletRequest request) {
       return this.lookupMultipartResolver();
   }

   protected MultipartResolver lookupMultipartResolver() {
       WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
       String beanName = this.getMultipartResolverBeanName();
       if (wac != null && wac.containsBean(beanName)) {
           if (this.logger.isDebugEnabled()) {
               this.logger.debug("Using MultipartResolver '" + beanName + "' for MultipartFilter");
           }

           return (MultipartResolver)wac.getBean(beanName, MultipartResolver.class);
       } else {
           return this.defaultMultipartResolver;
       }
   }
}

发现一个叫multipartResolverBeanName的参数,我们知道如何在javaweb项目里配置一个过滤器,需要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>commonsMultipartResolver</param-value>
   	</init-param>
</filter>
<filter-mapping>
   	<filter-name>multipartFilter</filter-name>
   	<url-pattern>/*</url-pattern>
</filter-mapping>

其中url-pattern只设置你项目里文件上传的路径,发现这里就可以随便定义文件上传解析器的id了,但是我们知道filter是优先于servlet初始化的,所以在DispatcherServlet初始化时加载的spring-mvc.xml定义的commonsMultipartResolver是找不到的,所以需要在context里加载的配置文件里定义,分别如下

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

spring-context.xml有下面定义

<bean id="commonsMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
   	<property name="maxUploadSize" value="${web.maxUploadSize}" />  
</bean>

StandardServletMultipartResolver

根据名字知道这个是标准servlet文件解析器,其中配置有两种配置跟上面类似,但是不需要依赖包,点开源码:

package org.springframework.web.multipart.support;

import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;

public class StandardServletMultipartResolver implements MultipartResolver {
    private boolean resolveLazily = false;

    public StandardServletMultipartResolver() {
    }

    public void setResolveLazily(boolean resolveLazily) {
        this.resolveLazily = resolveLazily;
    }

    public boolean isMultipart(HttpServletRequest request) {
        if (!"post".equals(request.getMethod().toLowerCase())) {
            return false;
        } else {
            String contentType = request.getContentType();
            return contentType != null && contentType.toLowerCase().startsWith("multipart/");
        }
    }

    public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException {
        return new StandardMultipartHttpServletRequest(request, this.resolveLazily);
    }

    public void cleanupMultipart(MultipartHttpServletRequest request) {
        try {
            Iterator var2 = request.getParts().iterator();

            while(var2.hasNext()) {
                Part part = (Part)var2.next();
                if (request.getFile(part.getName()) != null) {
                    part.delete();
                }
            }
        } catch (Exception var4) {
            LogFactory.getLog(this.getClass()).warn("Failed to perform cleanup of multipart items", var4);
        }

    }
}

发现这个更简单,而是利用了javax.servlet.http.Part,这个servlet3.0以上才有的类,也就说必须web容器支持servlet3.03.0以上,如下也有三种配置,第一种第二种类似上面

  1. spring-mvc.xml定义类型是StandardServletMultipartResolver、id为的multipartResolver的bean ,设置文件上传的最大字节数
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver">  
		<property name="maxUploadSize" value="${web.maxUploadSize}" />  
</bean>

2.web.xml定义一个MultipartFilter,spring-context.xml定义一个类型为定义类型是StandardServletMultipartResolver的bean

<bean id="standardServletMultipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver">  
   	<property name="maxUploadSize" value="${web.maxUploadSize}" />  
</bean>
<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>standardServletMultipartResolver</param-value>
   	</init-param>
</filter>
<filter-mapping>
   	<filter-name>multipartFilter</filter-name>
   	<url-pattern>/*</url-pattern>
</filter-mapping>
  1. 用multipart-config标签或者MultipartConfig注解,标签是web.xml,如下
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   version="3.0">
<servlet>
   <servlet-name>SpringDispatcher</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
   <init-param>
   		<param-name>contextConfigLocation</param-name>
   		<param-value>classpath*:/spring-mvc.xml</param-value>
   	</init-param>
   <multipart-config>
           <location>/tmp</location>
           <max-file-size>5242880</max-file-size><!--5MB-->
           <max-request-size>20971520</max-request-size><!--20MB-->
           <file-size-threshold>0</file-size-threshold>
   </multipart-config>
 </servlet>

标签如下用法

@MultipartConfig(location="/tmp",maxFileSize=5242880,maxRequestSize=20971520,fileSizeThreshold=0)//标识Servlet支持文件上传
public class UploadServlet extends HttpServlet {

我们在SpringMVC项目里可以继承DispatcherServlet,然后重写它方法

结语

到此我们五种使用清楚了,发现其中有四种配置类似,用了两种解析器。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值