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