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);