Spring Boot 文件上传原理解析
首先我们要知道什么是spring boot,这里简单说一下,spring boot可以看作是一个框架中的框架--->集成了各种框架,像security、jpa、data、cloud等等,它无须关心配置可以快速启动开发,有兴趣可以了解下自动化配置实现原理,本质上是 spring 4.0的条件化配置实现,深抛下注解,就会看到了。
说spring boot 文件上传原理 其实就是spring mvc,因为这部分工作是spring mvc做的而不是spring boot,那么,springmvc又是怎么处理文件上传这个过程的呢?
图:
首先项目启动相关配置,再执行上述第二步的时候 dispatcherservlet会去查找id为multipartresolver的bean,在配置中看到bean指向的是commonsmultipartresolve,其中实现了multipartresolver接口。
第四步骤这里会判断是否multipart文件即ismultipart方法,返回true:就会调用 multipartresolver 方法,传递httpservletrequest会返回一个multiparthttpservletrequest对象,再有dispatcherservlet进行处理到controller层;返回false:会忽略掉,继续传递httpservletrequest。
在mvc中需要在配置文件webapplicationcontext.xml中配置 如下:
<bean id="multipartresolver" class="org.springframework.web.multipart.commons.commonsmultipartresolver"> <property name="defaultencoding" value="utf-8"/> <property name="maxuploadsize" value="100000000"/> <property name="uploadtempdir" value="fileupload/temp"/> </bean>
而spring boot已经自动配置好,直接用就行,做个test没什么问题。有默认的上传限制大小,不过在实际开发中我们还是做一些配置的,
如下在application.properties中:
# multipart config #默认支持文件上传 spring.http.multipart.enabled=true #文件上传目录 spring.http.multipart.location=/tmp/xunwu/images/ #最大支持文件大小 spring.http.multipart.max-file-size=4mb #最大支持请求大小 spring.http.multipart.max-request-size=20mb
当然也可以写配置类来实现,具体的就不做展示了。
看完上述你肯定有个大概的了解了,这里再啰嗦下,spring提供multipart的解析器:multipartresolver,上述说的是commonsmultipartresolver,它是基于commons file upload第三方来实现,这也是在servlet3.0之前的东西,3.0+之后也可以不需要依赖第三方库,可以用standardservletmultipartresolver,同样也是实现了multipartresolver接口,我们可以看下它的实现:
* copyright 2002-2017 the original author or authors. package org.springframework.web.multipart.support; 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; /** * standard implementation of the {@link multipartresolver} interface, * based on the servlet 3.0 {@link javax.servlet.http.part} api. * to be added as "multipartresolver" bean to a spring dispatcherservlet context, * without any extra configuration at the bean level (see below). * * <p><b>note:</b> in order to use servlet 3.0 based multipart parsing, * you need to mark the affected servlet with a "multipart-config" section in * {@code web.xml}, or with a {@link javax.servlet.multipartconfigelement} * in programmatic servlet registration, or (in case of a custom servlet class) * possibly with a {@link javax.servlet.annotation.multipartconfig} annotation * on your servlet class. configuration settings such as maximum sizes or * storage locations need to be applied at that servlet registration level; * servlet 3.0 does not allow for them to be set at the multipartresolver level. * * @author juergen hoeller * @since 3.1 * @see #setresolvelazily * @see httpservletrequest#getparts() * @see org.springframework.web.multipart.commons.commonsmultipartresolver */ public class standardservletmultipartresolver implements multipartresolver { private boolean resolvelazily = false; /** * set whether to resolve the multipart request lazily at the time of * file or parameter access. * <p>default is "false", resolving the multipart elements immediately, throwing * corresponding exceptions at the time of the {@link #resolvemultipart} call. * switch this to "true" for lazy multipart parsing, throwing parse exceptions * once the application attempts to obtain multipart files or parameters. */ public void setresolvelazily(boolean resolvelazily) { this.resolvelazily = resolvelazily; } @override public boolean ismultipart(httpservletrequest request) { // same check as in commons fileupload... if (!"post".equals(request.getmethod().tolowercase())) { return false; } string contenttype = request.getcontenttype(); return (contenttype != null && contenttype.tolowercase().startswith("multipart/")); } @override public multiparthttpservletrequest resolvemultipart(httpservletrequest request) throws multipartexception { return new standardmultiparthttpservletrequest(request, this.resolvelazily); } @override public void cleanupmultipart(multiparthttpservletrequest request) { // to be on the safe side: explicitly delete the parts, // but only actual file parts (for resin compatibility) try { for (part part : request.getparts()) { if (request.getfile(part.getname()) != null) { part.delete(); } } } catch (throwable ex) { logfactory.getlog(getclass()).warn("failed to perform cleanup of multipart items", ex); } } }
这里是之前写的test的后者实现配置类,可以简单看下,作为了解:
package com.bj.config; import org.springframework.boot.autoconfigure.condition.conditionalonmissingbean; import org.springframework.boot.autoconfigure.web.multipartproperties; import org.springframework.boot.context.properties.enableconfigurationproperties; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import org.springframework.web.multipart.multipartresolver; import org.springframework.web.multipart.support.standardservletmultipartresolver; import org.springframework.web.servlet.dispatcherservlet; import javax.servlet.multipartconfigelement; @configuration @enableconfigurationproperties(multipartproperties.class) public class fileuploadconfig { private final multipartproperties multipartproperties; public fileuploadconfig(multipartproperties multipartproperties){ this.multipartproperties=multipartproperties; } /** * 注册解析器 * @return */ @bean(name= dispatcherservlet.multipart_resolver_bean_name) @conditionalonmissingbean(multipartresolver.class) public standardservletmultipartresolver multipartresolver(){ standardservletmultipartresolver multipartresolver = new standardservletmultipartresolver(); multipartresolver.setresolvelazily(multipartproperties.isresolvelazily()); return multipartresolver; } /** * 上传配置 * @return */ @bean @conditionalonmissingbean public multipartconfigelement multipartconfigelement(){ return this.multipartproperties.createmultipartconfig(); } }
总结
以上所述是小编给大家介绍的spring boot 文件上传原理解析,希望对大家有所帮助