问题发生

近期,在线上有出现问题;截图如下:

仔细一看,是 /tmp/tomcat...... ;大家的第一反应是,呃,是不是 basedir 没有设置,跑到临时目录去了;所以,请运维同学 设置上 basedir 的配置。之后过了N天,依然出现了这样的问题;

问题分析

注意,我们看看错误截图中的内容,是 /tmp/tomcat­docbase.xxxx ;注意,是tomcat­docbase ,而不是 tomcat ;tomcat­docbase 是怎么出来的呢?是否和 tomcat.basedir 有关系呢?需要继续排查;

我们也检查了代码的位置,发现代码中,是将文件输出到了一个目录下;而这个目录的代码:

String outFilePath = request.getServletContext().getRealPath("/") + "upload/";

那么,是否: request.getServletContext().getRealPath("/") 这部分和basedir没有关系的呢?

tomcat的临时目录设置

大家都知道在springboot 1.x 中的临时目录设置方法;配置文件中加上一段:

server.tomcat.basedir=xxxxx 

也都知道,如果不设置这个的话,会在 java.io.tmpdir 环境变量目录下,出现一个tomcat.xxxx.port(服务端口号) 的目录作为临时 目录; 同时我们也都清楚,在linux 下 java.io.tmpdir ,如果没有特殊设置,默认是指向到: /tmp 目录下,而这个目录是在linux 下是 有定时任务 定期清理的;也就是说,如果我们不设置basedir ,那么真的是会出现以上的类似的错误,就是提醒:xxx 目录不存在之 类的;

而没有设置 basedir ,那么在 临时目录下出现的 tomcat 目录应该是:

tomat­-docbase 和 basedir有关系吗?

看这部分,自然翻代码;springboot 是内嵌tomcat的;找到 TomcatEmbeddedServletContainerFactory 这个类,这个是tomcat 内 嵌的时候,相关的启动类;找到 getEmbeddedServletContainer 的方法,如下:

这部分方法中,可以看到; 1)setBaseDir ,这个上下翻一下逻辑,是我们设置的 basedir ,那如果我们不设置 basedir,会自动创建一个 tomcat 开头的临时目 录:createTempDir(String),这个方法,入参是:tomcat ;而createTempDir 如下所示:

在这儿,我们可以确认,所谓的 tomcat­docbase.xxx ,不是我们的 basedir 没设置引起的;因为即使我们不设置,那么目录也不会 是tomcat­docbase;

继续

接着,还是 TomcatEmbeddedServletContainerFactory ,我们继续;看到了 prepareContext 的方法;这个方法,是初始化 Context的,是否和我们 要找的 tomcat­docbase有关系;代码如下:

确实是在这里了;翻了一下代码逻辑:getValidDocumentRoot(),在内嵌tomcat容器启动的时候,返回是空的;所以这部分的目录就 变成临时目录下 tomcat­docbase.xxx 的目录;

而 request.getServletContext().getRealpath(“/”),获取的就是这个目录;

自此,我们找到了源头;

如何设置docbase

查看:getValidDocumentRoot方法:

实际上,在整个使用中,我们虽然找到了 setDocumentRoot() 方法,但没有找到调用方;因此默认的DocumentRoot也就无法设置, 当然我们可以自己重写这部分代码来实现;

docbase 的测试验证

1. 默认,仅设置base.dir

说明,baseDir 的设置,不影响docBase

2. 在部署目录中,增加了一个 public 文件夹

部署目录如下 :

输出如下:

看代码中的 getCommonDocumentRoot() 实现可以知道原因;

3. 设置 java.io.tmpdir 变量

输出如下:

有个前提条件,上面第2个的 public 目录要删除掉;否则还会在那个public 目录下;

问题定位

由于我们没有设置 java.io.tmpdir 环境变量,而又使用了 request.getServletContext().getRealPath("/") 来获取目录;导致文 件目录被定位到:/tmp/tomcat­docbase.xxx 目录下;

根据linux的规则,/tmp 目录下文件,会定期清理,导致一段时间之后,写 入: request.getServletContext().getRealPath("/") 目录下,出现异常:文件或者目录找不到;

之前一直认为的 basedir 参数设置,并不会影响到 request.getServletContext().getRealPath("/") 的取值,因此原来的解决 方法并没有效果;

问题的解决方法

1. 最简单的方式 启动脚本加上对 java.io.tmpdir 的参数设置; 同样的,我们也知道 java.io.tmpdir ,在不设置 basedir 下的时候,也会调整basedir的目录;因此,可以通过java.io.tmpdir进行 统一设置; 其实,在tomcat 自身的启动脚本中,也有类似的控制,如下:(tomcat bin\catalina.sh文件)

所以,可以在启动脚本中,获取到应用的当前目录,并将 java.io.tmpdir 设置到当前目录下的某个文件,例如:tmp;

2. 在部署目录下增加 public 文件夹 这种方式下,需要重新修改提供的部署包,暂时不推荐

3. 修改代码 由于是下载文件中,需要临时生成一个文件,而临时文件用了 request.getServletContext().getRealPath("/") 来获取目 录,导致了问题; 这部分代码修改掉,可以直接使用 File.createTempFile() ,来创建临时文件;这样就可以完全避免上面的问题;当然这个只 是解决我们目前的这个问题;

tomcat的 docBase 、workDir 关系

如果我们将应用打包为 war 部署到tomcat 应用下的时候,最简单的方式是,将war包复制到 webapp 目录下,tomcat自行加载就可以 了; 但其实,还有一种方式,就是通过 tomcat的 server.xml 文件,而这个server.xml文件中,是可以配置应用目录及上下文;

<Context docBase="D:\samples\WebRoot" path="/sample" reloadable="true" />

<!-- Context 表示运行在虚拟主机上的一个web应用程序,通常为WAR文件 -->

<!-- docBase 应用程序的路径或者是WAR文件存放的路径 -->

<!-- path 表示此web应用程序的url的前缀,就我们所说的请求上下文,这样请求的url为http://localhost:8080/**** -->

<!-- reloadable 这个属性非常重要,如果为true,则tomcat会自动检测应用程序的/WEB-INF/lib 和/WEB-INF/classes目录 的变化,自动装载应用程序,我们可以在不重起tomcat的情况下改变应用程序 -->

docBase 其实是用于设置我们的应用部署的目录;而内置的tomcat 容器,启动之后,也会自行创建一个这个目录(默认就在 java.io.tmpdir 指定的 tomcat­docbase.xxx 下);

workDir,是指tomcat 在运行中,会生成一些临时文件(比如 jsp 编译之后的 java / class 文件);而这些是放在了 workDir 下;如果 是应用部署在tomcat 服务中,则在tomcat 目录下,有个:/work/Catalina/localhost 目录是用于保存这个;而在springboot 的内嵌 tomcat 中,则是通过 basedir 来指定目录;

SpringBoot 内置tomcat 的 request.getServletContext().getRealPath(“/”) 问题与tomat­-docbase 和 basedir的关系相关推荐

  1. 优化之SpringBoot 内置tomcat 调优测试

    问题 怎么配置springBoot 内置tomcat,才能使得自己的服务效率更高呢? 基础配置 Spring Boot 能支持的最大并发量主要看其对Tomcat的设置,可以在配置文件中对其进行更改.我 ...

  2. SpringBoot内置tomcat出现error:An incompatible version [1.1.32] of the APR based Apache Tomcat Native lib

    SpringBoot内置tomcat出现error:An incompatible version [1.1.32] of the APR based Apache Tomcat Native lib ...

  3. SpringBoot内置Tomcat支持多大并发量和连接数

    SpringBoot内置Tomcat,再默认设置中,Tomcat的最大线程数是200,最大连接数是10000.支持的并发量是指连接数,200个线程如何处理10000条连接的? Tomcat有两种处理连 ...

  4. SpringBoot内置tomcat出现APR版本过低解决办法

    SpringBoot内置tomcat出现error:An incompatible version [1.1.32] of the APR based Apache Tomcat Native lib ...

  5. Springboot内置Tomcat配置参数调优

    Springboot内置Tomcat配置参数调优,首先,线程数是一个重点,每一次HTTP请求到达Web服务器,Web服务器都会创建一个线程来处理该请求,该参数决定了应用服务同时可以处理多少个HTTP请 ...

  6. SpringBoot内置Tomcat启动不了的原因

    SpringBoot内置Tomcat启动不了的原因: 1.需要加入spring-boot-starter-web依赖 [web中集成了tomcat.dispatcherServlet.xml-] &l ...

  7. SpringBoot 内置 Tomcat 线程数优化配置,你学会了吗?

    前言 本文解析springboot内置tomcat调优并发线程数的一些参数,并结合源码进行分析 参数 线程池核心线程数 server.tomcat.min-spare-threads:该参数为tomc ...

  8. SpringBoot内置tomcat启动原理

    前言 不得不说SpringBoot的开发者是在为大众程序猿谋福利,把大家都惯成了懒汉,xml不配置了,连tomcat也懒的配置了,典型的一键启动系统,那么tomcat在springboot是怎么启动的 ...

  9. SpringBoot内置Tomcat浅析

    一.SpringBoot框架内置Tomcat,开发非常方便,随着SpringBoot的框架升级,内置Tomcat也更新版本.本文SpringBoot框架版本:2.2.10. 1.如何查看SpringB ...

最新文章

  1. C++中函数的默认参数
  2. WPF中用于嵌入其他进程窗口的自定义控件(AppContainer)
  3. Wpf TextChanged事件导致死循环,事件触发循环问题
  4. 1013 数素数 (20分)
  5. 【格局】一张图看懂全球人工智能竞争格局|湾区人工智能
  6. 查看usb控制器固件日期_三星发布两款USB Type-C电源控制器芯片 支持100W的充电功率...
  7. VMware vSAN的相关告警处理 2021-01-04
  8. 解决Caused by: GSSException: (Mechanism level: Failed to find any Kerberos tgt)
  9. 【论文解读】图文并茂带你细致了解ELMo的各种细节
  10. solidworks中皮带同步轮配合如何做?几张图教会你
  11. Hadoop HA架构图
  12. html制作一个视频播放器,H5 打造属于自己的视频播放器(HTML 篇)
  13. ubuntu GStreamer + QT多媒体播放器开发(三)
  14. python爬虫学习之路1
  15. 解开Kafka神秘的面纱(二):Kafka的高效读写与消息安全
  16. 视频显著性检测----《Flow Guided Recurrent Neural Encoder for Video Salient Object Detection》
  17. 无迹卡尔曼滤波(UKF)超详细解释
  18. 1.回文是指正读和反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。试写一个算法判定给定的字符向量是否为回文。(提示:将一半字符入栈。)2.假设以带头结点的循环链
  19. ubuntu linux 环境下的程序打包
  20. pap认证失败_路由器PAP:密码验证失败.无法上网

热门文章

  1. xshell6 和 xftp6 官网免费下载
  2. c语言版的用两个栈实现一个队列
  3. 广西南宁商际网络淘宝天猫托管代运营/电商培训顾问外包服务商
  4. k8s学习-思维导图与学习笔记
  5. 应用场景五: 西门子PLC通过Modbus协议连接DCS系统
  6. 推荐图灵出版社的图书
  7. 【变量创建】CFPS应用及C刊变量复盘STATA实战1
  8. 内网穿透在家远程连接公司电脑
  9. 火狐网页对话框_默认情况下,在Firefox中展开“添加书签”对话框
  10. 三维数字沙盘电子沙盘M3DGIS地理信息立体显示系统开发教程第9课