Fly1000007 2025-11-25 16:50 采纳率: 0%
浏览 3

tomcat9.0.112 的一个奇特现象

tomcat9.0.112 centos系统 java1.8

在这样的路径下放置有js静态资源文件。是通过war包方式进行发布的
webapps/ROOT/WEB-INF/classes/static/wapb2b/static/js/40.js

tomcat正常运行启动之后,服务也可以正常工作

目前问题是:
当删除了40.js之后,浏览器访问显示404没有了这个文件。但是,当我再次将40.js文件复制到对应目录下之后,再次浏览器访问还是404,必须要重启tomcat之后,40.js才会被重新识别。

设置了缓存禁用依然没有任何效果,是否tomcat9.0.112本身已经不支持这种方式

  • 写回答

2条回答 默认 最新

  • 檀越@新空间 2025-11-25 16:58
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    你提到的问题非常典型,涉及到 Tomcat 9.0.112 在部署静态资源时的行为。以下是详细的分析和解决方案。


    🧩 问题现象总结

    • 静态资源文件路径为:
      webapps/ROOT/WEB-INF/classes/static/wapb2b/static/js/40.js
    • 正常启动后可以访问该文件。
    • 删除文件后,浏览器返回 404。
    • 重新复制文件后,浏览器仍返回 404必须重启 Tomcat 才能恢复访问
    • 已尝试禁用浏览器缓存,但无效。
    • 疑问:是否 Tomcat 9.0.112 不支持这种部署方式?

    🔍 问题原因分析

    1. 静态资源的加载机制

    在 Tomcat 中,WEB-INF 目录下的内容是受保护的,默认情况下,不能直接通过 HTTP 访问这些目录中的资源。例如:

    webapps/ROOT/WEB-INF/classes/static/...
    

    虽然你可以将静态资源放在 WEB-INF/classes/ 下(如通过 Maven 或 Gradle 构建),但这些资源通常会被打包进 JAR 文件中,而不是以原始文件形式存在。

    注意: 如果你手动将 .js 文件放到了 WEB-INF/classes/static/...,Tomcat 不会自动识别这些文件,因为它们不在公开可访问的路径下。


    2. 为什么删除后无法恢复?

    当文件被删除后,Tomcat 可能已经将其缓存到内存中或某些内部结构中,并不会立即重新加载。即使你重新复制了文件,Tomcat 没有触发重新加载机制,所以浏览器仍然找不到文件。


    3. Tomcat 的热部署限制

    Tomcat 9.0.112 对于 WAR 包部署的 Web 应用,不支持对 WEB-INF 下文件的热更新(即无需重启即可生效)。


    ✅ 解决方案

    1. 将静态资源放在 webapps/ROOT/ 下的公开目录中

    Tomcat 默认允许访问 webapps/ROOT/ 下的内容,因此建议将静态资源放置在以下路径中:

    webapps/ROOT/static/wapb2b/static/js/40.js
    

    然后通过如下 URL 访问:

    http://localhost:8080/static/wapb2b/static/js/40.js
    

    优点: 支持热更新,无需重启 Tomcat 即可生效。


    2. 配置 web.xml 以允许访问 WEB-INF 下的资源(不推荐)

    如果你坚持要使用 WEB-INF/classes/ 路径,可以通过修改 web.xml 来允许访问该目录,但这种方式不推荐,因为它可能带来安全风险。

    <!-- webapps/ROOT/WEB-INF/web.xml -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Allow access to static resources</web-resource-name>
            <url-pattern>/static/*</url-pattern>
        </web-resource-collection>
        <auth-constraint />
    </security-constraint>
    

    但请注意,即使这样配置,Tomcat 也不会动态加载 WEB-INF/classes/ 下的文件,除非你使用 JAR 包


    3. 使用 WAR 包部署方式

    如果你使用的是 WAR 包发布方式,请确保你的静态资源被正确打包进 WAR 包中,并且位于 WEB-INF/classes/ 或其他非受保护目录中。

    ✅ 正确的项目结构示例:

    src/main/resources/static/wapb2b/static/js/40.js
    

    构建后,Tomcat 会将这些资源打包进 WAR 包的:

    WEB-INF/classes/static/wapb2b/static/js/40.js
    

    但此时你无法直接访问这个路径,因为它是 WEB-INF 下的内容。


    4. 使用外部资源目录(推荐)

    你可以配置 Tomcat 的 context.xml 文件,将外部目录映射到 Web 应用中:

    修改 conf/Catalina/localhost/ROOT.xml

    <Context docBase="/path/to/your/static/files" />
    

    然后访问:

    http://localhost:8080/static/wapb2b/static/js/40.js
    

    优点: 实现热更新,无需重启 Tomcat。


    5. 代码层面处理(如果必须使用 WEB-INF/classes/

    如果你确实需要将静态资源放在 WEB-INF/classes/,并且希望它能被访问,可以通过 Java 代码读取并响应:

    示例代码(Servlet):

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String path = "/static/wapb2b/static/js/40.js";
        InputStream is = getServletContext().getResourceAsStream(path);
        if (is != null) {
            response.setContentType("application/javascript");
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                response.getOutputStream().write(buffer, 0, length);
            }
        } else {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
    }
    

    然后通过如下 URL 访问:

    http://localhost:8080/your-servlet-path
    

    ⚠️ 总结

    | 问题 | 原因 | 解决方案 | |------|------|----------| | 404 错误 | WEB-INF 下的资源无法被直接访问 | 将静态资源移至公开目录(如 webapps/ROOT/) | | 热更新失败 | Tomcat 不支持 WEB-INF 下文件的热更新 | 使用外部资源目录或 WAR 包方式部署 | | 必须重启才能生效 | Tomcat 缓存机制 | 使用外部资源目录或 Servlet 动态读取 |


    🧾 最终建议

    强烈建议:
    将静态资源放在 webapps/ROOT/ 下的公开目录中,避免使用 WEB-INF/classes/ 存放静态文件。


    如果你愿意提供完整的项目结构或 web.xmlcontext.xml 内容,我可以进一步帮你优化配置。

    评论

报告相同问题?

问题事件

  • 创建了问题 11月25日