Tomcat 的 work 目录缓存导致的JSP页面图片更新问题

一、问题分析

1. 修改后重新部署没有变化

笔者之前部署了一个后台管理项目,通过它来发布课程内容,其中有一个 JSP 课程页面,在该 JSP 页面里也引用了类文件 Constant.java 里的一个变量(ALIYUN_OSS_PATH),该变量的值是一个域名地址(static.aaa.com ),在该 JSP 页面基于这个地址来加载和显示图片(static.aaa.com/x.png)。

复制代码
# 在 jsp 页面获取 java 类的变量值
<c:set var="aliyun" value="<%=com.xxx.admin.common.Constants.ALIYUN_OSS_PATH%>"/>

现在因为项目需要,在 Constant.java 文件里更改了这个该变量的值:

复制代码
//修改前
//public static final String ALIYUN_OSS_PATH = "http://static.aaa.com/";
//修改后
public static final String ALIYUN_OSS_PATH = "http://static.bbb.com/";

然后重新部署,但是却发现所有的图片都打不开了。但是在浏览器展示的页面上拷贝图片地址,发现与和之前的图片地址没有任何变化:static.aaa.com/x.png , 本来希望出现的变化是:static.bbb.com/x.png

总之一句话,就是项目修改并重新部署后 JSP 页面的图片路径没有更新。

2. 图片无法正常显示分析

原先浏览器入口路径是 admin.aaa.com, 图片请求地址是:static.aaa.com/x.png

现在浏览器入口路径是 admin.bbb.com, 图片请求地址仍然是:static.aaa.com/x.png, 并没有变成我希望的修改后的 static.bbb.com.

这里图片为什么之前能打开?现在重新部署后,路径没有变化为什么反而打不开呢?这个与部署后,进入网站后台入口地址发生了变化有关系:

浏览器是通过 admin.aaa.com 进入后台管理,发起请求时,http 头的 referer url 路径就是入口路径:admin.aaa.com ,这与 OSS 服务端设置的 referrer url 白名单一致,所以能正常打开图片。现在更新部署后,请求的图片路径没有变化,仍然是 static.aaa.com/x.png ,但是管理后台的入口地址变更为: admin.bbb.com , 所以 header 头里带的 referer url 路径就变成 admin.bbb.com . 这个与 OSS 服务端设置的 refer url白名单不一致,所以导致图片无法正常请求。

通过 referer url 实现"访问控制 ",其原理可以可以参考: <HTML页面跨域请求图片资源报错>

二、问题排查

一开始是怀疑浏览器的缓存导致,重新清理了浏览器的缓存重启浏览器,再次打开后台页面,仍然没有任何改变。

问题进一步排除,继续去查看项目部署后台的文件,发现有更新的 java源文件,在编译后的 class 文件确实已经更新完毕。为什么 jsp 页面图片就是无法正常打开了。

排除了以上问题后,开始怀疑在【服务端的Tomcat是否有类似浏览器一样的缓存】 ,经过查询后,定位到了 Tomcat 下的 WORK 目录。原来所有的 JSP 页面都会编译成 _jsp.java_jsp.class 文件,存储在这个目录下,如果 jsp 发生了改变,tomcat 会重新编译,在前端请求时候将重新编译后的 _jsp.class文件载入内存:

现在问题明白了。因为我的 JSP 文件引用 java 类文件了的 oss 路径变量:

复制代码
<c:set var="aliyun" value="<%=com.xxx.admin.common.Constants.ALIYUN_OSS_PATH%>"/>

虽然我修了 java 源代文件里的 ALIYUN_OSS_PATH 变量的值后重新部署,但是 work 目录下的 JSP 文件本身没有进行任何修改,所以在重新部署后,JSP 不会重新编译,在发起请求时,tomcat 仍然调用的是之前缓存的 _jsp.class 文件,该文件里面 ALIYUN_OSS_PATH 值并没更新。所以图片加载地址就没有变化,仍然是之前的:static.aaa.com/x.png , 而不是更新后的 static.bbb.com/x.png

三、问题解决

方式1:

清理 Tomcat 缓存,我们可以通过执行下面的命令:

复制代码
rm -rf /path/to/tomcat/work/*

方式2:

用 RD 命令删除整个目录,只需打开 tomcat/bin/startup.bat 文件,在开头加入:

复制代码
rd/s/q "/Tomcat path/work/Catalina"

这样每次启动Tomcat的时候就会先删除页面缓存了,不用担心页面修改后没被重新编译。

四、总结

如果 JSP 的引用了 java 源代码里的变量。如果该变量的值发生了变化,在重新部署后,记得将Tomcat 下 work 目录里对应的 JSP 文件的缓存进行清理。

相关推荐
Geek-Chow12 分钟前
CountDownLatch in Java
java
SL_staff43 分钟前
从RBAC到场景化授权:《无忧·企业文档》三级权限模型的技术实践解析
java·开源·产品
传奇开心果编程1 小时前
【springboot基础语法学与练】第 1 课:从零开始
java·spring boot·后端·学习
SL_staff1 小时前
财务系统慎用低代码?从数据模型闭环看合规落地的技术实践
java·低代码·全栈
滕州市燕猫虎计算机科技工作室个体工商户2 小时前
IDEA:Command line is too long
java·ide·intellij-idea
步行cgn2 小时前
Spring p 命名空间注入详解
java·前端·spring
YatHinLay2 小时前
MyBatis 流式查询实战:ResultHandler 处理海量数据
java
天天被压力3 小时前
【跨市场数据实战 #08】可转债折价机会怎么筛:3个接口抓比价、列表和实时盘口
java·人工智能·python
张某布响丸辣3 小时前
附件下载的安全边界:路径白名单、NAS 哨兵文件与 Redis Lua 一次性令牌
java·redis·redis lua·nas哨兵
YatHinLay4 小时前
Spring Boot + Calcite 实现跨库查询
java