Spring MVC源码解析 - MultipartResolver组件

给你一囗甜甜゛ 提交于 2020-01-24 22:08:35

目录

一. MultipartResolver  

 二. StandardServletMultipartResolver

三.  CommonsMultipartResolver


一. MultipartResolver  

/**
 * 依照<a href="https://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>,对于二进制文件上传的策略接口。
 * 在一个应用程序上下文和单机模式,都是可使用的。
 *
 * 对于Spring 3.1来说,有两个具体的实现类:
 * {@link org.springframework.web.multipart.commons.CommonsMultipartResolver}
 * for Apache Commons FileUpload
 * {@link org.springframework.web.multipart.support.StandardServletMultipartResolver}
 * for the Servlet 3.0+ Part API
 *
 * 对于Spring的DispatcherServlet没有默认的解析器实现,因为一个应用程序可能自己选择去分析它的二进制请求。
 * 为了定义一个实现类,创建一个id为“multipartResolver”在DispatcherServlet中的application context里。
 * 这样的一个解析器会应用到DispatchServlet的所有请求中
 *
 * 如果一个DispatcherServlet发现了一个二进制请求,会通过配置的MultipartResolver进行解析并且传递一个包装的HttpServletRequest。
 * 控制器这时候可以将给定的请求转换成MultipartHttpServletRequest接口,这个接口允许访问任何MultipartFile。
 * 注意:这个转换仅仅是在一个二进制请求中得到支持。
 *
 * <pre class="code">
 * public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
 *   MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
 *   MultipartFile multipartFile = multipartRequest.getFile("image");
 *   ...
 * }</pre>
 *
 * 没有直接访问,命令或者控制器可以注册一个ByteArrayMultipartFileEditor或者StringMultipartFileEditor带有它们的数据绑定器
 * 自动将二进制内容转换形成bean属性。
 *
 * 作为使用一个带有DispatcherServlet的MultipartResolver的一个选项,MultipartFilter可以被注册到web.xml中。
 * 它委派给root application context中的MultipartResolver类型的bean。这个主要是针对的是没有Spring MVC框架的应用程序。
 *
 * 注意:从来也不需要从代码层面去访问MultipartResolver。它简单地在幕后工作,使MultipartHttpServletRequest对于控制器可用。
 */
public interface MultipartResolver {

	/**
	 * 确定给定的请求是否包含二进制内容。
	 * 将会检查内容类型“multipart/form-data”,但是实际接收的请求可能依赖于解析器的实现类。
	 */
	boolean isMultipart(HttpServletRequest request);

	/**
	 * 将给定的http请求解析成二进制文件和参数,然后包装请求成一个MultipartHttpServletRequest对象。
	 * 这个对象,提供对文件描述符的访问和使内含的参数可以访问,通过标准的ServletRequest方法。
	 */
	MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException;

	/**
	 * 清理二进制处理的任何资源,比如上传文件的一个存储。
	 */
	void cleanupMultipart(MultipartHttpServletRequest request);

}

 二. StandardServletMultipartResolver

/**
 * MultipartResolver的标准实现接口,基于Servlet 3.0的 {@link javax.servlet.http.Part} API。
 * 在一个Spring DispatcherServlet上下文中,添加"multipartResolver"bean,没有任何额外的代码级别的配置。
 *
 * 注意:为了使用基于二进制解析的Servlet 3.0,你需要标记在web.xml中“multipart-config”部分的受到影响的servlet,
 * 或者使用以编程式的servlet注册的MultipartConfigElement或者在servlet class中的使用MultipartConfig注解。
 * 例如最大的文件大小或者存储位置的配置设置使用的是servlet注册的级别;Servlet3.0不允许以MultipartResolver中设置它们。
 *
 * public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
 *	 // ...
 *	 @Override
 *	 protected void customizeRegistration(ServletRegistration.Dynamic registration) {
 *     // Optionally also set maxFileSize, maxRequestSize, fileSizeThreshold
 *     registration.setMultipartConfig(new MultipartConfigElement("/tmp"));
 *   }
 * }
 */
public class StandardServletMultipartResolver implements MultipartResolver {

	private boolean resolveLazily = false;


	/**
	 * 设置是否在访问文件或者参数的时候,延迟解析二进制请求。
	 * 默认是false。
	 */
	public void setResolveLazily(boolean resolveLazily) {
		this.resolveLazily = resolveLazily;
	}


	@Override
	public boolean isMultipart(HttpServletRequest request) {
		// 内容类型以"multipart/"开头
		return StringUtils.startsWithIgnoreCase(request.getContentType(), "multipart/");
	}

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

	/**
	 * 实际删除的是Part
	 */
	@Override
	public void cleanupMultipart(MultipartHttpServletRequest request) {
		if (!(request instanceof AbstractMultipartHttpServletRequest) ||
			    // MultiValueMap<String, MultipartFile> != null
				((AbstractMultipartHttpServletRequest) request).isResolved()) {
			// 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);
			}
		}
	}

}

三.  CommonsMultipartResolver

暂时放置,以后会完善的。

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!