文件上传时各配置目录优先级详解

Tomcat配置目录有以下两个

1.spring.servlet.multipart.location:文件上传路径

2.server.tomcat.basedir:配置Tomcat运行日志和临时文件的目录。

如果生产中配置了这两个目录,当上传文件时,他们的优先级是?

       当上传文件时,代码执行到Request类,在发现使用时spring.servlet.multipart.location优先级高,源码可见Request类中的parseParts方法中的以下代码段。

            File location;
            //取MultipartConfigElement这个对象中的location属性即 
            //spring.servlet.multipart.location配置的值
            String locationStr = mce.getLocation();
            if (locationStr == null || locationStr.length() == 0) {
                //取server.tomcat.basedir配置的值
                location = ((File) context.getServletContext().getAttribute(
                        ServletContext.TEMPDIR));
            } else {
                // If relative, it is relative to TEMPDIR
                location = new File(locationStr);
                if (!location.isAbsolute()) {
                    location = new File(
                            (File) context.getServletContext().getAttribute(
                                        ServletContext.TEMPDIR),
                                        locationStr).getAbsoluteFile();
                }
            }

在上面的代码段中可以得出上传文件时

spring.servlet.multipart.location的优先级比server.tomcat.basedir的高。

源码分析:

 spring.servlet.multipart.location通过MultipartAutoConfiguration 这个类进行赋值。并通过该类中的以下方法注入MultipartConfigElement这个Bean。

spring.servlet.multipart.location未配置时取ServletContext.TEMPDIR属性的值。

context.getServletContext().getAttribute(
        ServletContext.TEMPDIR)

其中ServletContext.TEMPDIR值为javax.servlet.context.tempdir,以该值为KEY.其值对应的value是在StandardContext类中的postWorkDirectory方法中设置到Map里去的。postWorkDirectory方法在tomcat启动时调用的startInternal方法里被调用。

其赋值源于

try {
    catalinaHomePath = getCatalinaBase().getCanonicalPath();
    dir = new File(catalinaHomePath, workDir);
} catch (IOException e) {
    log.warn(sm.getString("standardContext.workCreateException",
            workDir, catalinaHomePath, getName()), e);
}

catalinaHomePath的值源自Tomcat类中的initBaseDir方法赋值,赋的值依赖Tomcat类中的basedir属性,该属性是通过TomcatReactiveWebServerFactory类里的getWebServer方法赋值。basedir的值源自this.baseDirecotry。

public WebServer getWebServer(HttpHandler httpHandler) {
		Tomcat tomcat = new Tomcat();
        //baseDirectory属性来源于TomcatWebServerFactoryCustomizer#customize方法
		File baseDir = (this.baseDirectory != null) ? this.baseDirectory
				: createTempDir("tomcat");
		tomcat.setBaseDir(baseDir.getAbsolutePath());
		Connector connector = new Connector(this.protocol);
		tomcat.getService().addConnector(connector);
		customizeConnector(connector);
		tomcat.setConnector(connector);
		tomcat.getHost().setAutoDeploy(false);
		configureEngine(tomcat.getEngine());
		TomcatHttpHandlerAdapter servlet = new TomcatHttpHandlerAdapter(httpHandler);
		prepareContext(tomcat.getHost(), servlet);
		return new TomcatWebServer(tomcat, getPort() >= 0);
}

其中的baseDirectory是通过WebServerFactoryCustomizerBeanPostProcessor后置处理器通过         postProcessBeforeInitialization调用了函数的WebServerFactoryCustomizercustomize方法。该函数方法实际调用的时TomcatWebServerFactoryCustomizer中的customize方法。在该方法中可以看到下面的一段代码。该代码将server.tomcat.basedir配置的值赋值到ConfigurableTomcatWebServerFactory类型的对象中。

propertyMapper.from(tomcatProperties::getBasedir).whenNonNull()
      .to(factory::setBaseDirectory);

你可能感兴趣的:(tomcat)