You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Tomcat运行时获取依赖JAR列表并兼容SpringBoot?

解决SpringBoot与Tomcat环境下获取所有依赖JAR及Manifest信息的问题

Tomcat的类路径机制说明

Tomcat采用分层类加载器架构,System.getProperty("java.class.path")仅能返回Tomcat启动时的系统级类路径(也就是你看到的bootstrap.jar、tomcat-juli.jar等核心JAR)。而WAR包中应用自身的依赖JAR(WEB-INF/lib目录下)、编译后的类文件(WEB-INF/classes)由Tomcat的Web应用类加载器负责加载,这部分路径不会出现在系统类路径中,这就是部署到Tomcat后无法获取应用依赖的原因。

兼容SpringBoot与Tomcat环境的解决方案

核心思路是识别当前运行环境,分情况获取对应路径下的JAR资源:

1. 环境判断方法

可通过以下方式区分环境:

  • 检查是否存在SpringBoot内嵌容器特征类,比如org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory
  • 读取系统属性spring.boot.version,不为空则为SpringBoot内嵌环境
  • 判断是否能获取到ServletContext(Tomcat部署时,Web应用可通过该对象访问资源)

2. 分环境获取JAR列表

情况一:SpringBoot内嵌容器环境

继续使用System.getProperty("java.class.path")获取类路径,解析路径字符串后遍历处理:

  • 直接处理.jar文件
  • 递归遍历文件夹下的所有.jar文件

示例代码(Java 8兼容):

String classPath = System.getProperty("java.class.path");
String pathSeparator = System.getProperty("path.separator");
String[] paths = classPath.split(pathSeparator);

for (String path : paths) {
    File file = new File(path);
    if (file.isFile() && file.getName().endsWith(".jar")) {
        try (InputStream is = new FileInputStream(file);
             JarInputStream jarIs = new JarInputStream(is)) {
            Manifest manifest = jarIs.getManifest();
            // 处理JAR文件名及Manifest信息
        } catch (IOException e) {
            // 异常处理逻辑
        }
    } else if (file.isDirectory()) {
        traverseDirectory(file);
    }
}

// 递归遍历文件夹的工具方法
private static void traverseDirectory(File dir) {
    File[] files = dir.listFiles();
    if (files == null) return;
    for (File f : files) {
        if (f.isFile() && f.getName().endsWith(".jar")) {
            // 复用上述JAR处理逻辑
        } else if (f.isDirectory()) {
            traverseDirectory(f);
        }
    }
}

情况二:Tomcat部署的WAR环境

通过ServletContext获取WEB-INF/lib下的所有JAR资源,逐个读取Manifest:

示例代码(Java 8兼容):

// 可通过Spring的@Autowired注入ServletContext,或在Servlet的init方法中获取
Set<String> libPaths = servletContext.getResourcePaths("/WEB-INF/lib/");
if (libPaths != null) {
    for (String path : libPaths) {
        try (URL resourceUrl = servletContext.getResource(path);
             InputStream is = resourceUrl.openStream();
             JarInputStream jarIs = new JarInputStream(is)) {
            Manifest manifest = jarIs.getManifest();
            String jarName = path.substring(path.lastIndexOf("/") + 1);
            // 处理JAR文件名及Manifest信息
        } catch (IOException e) {
            // 异常处理逻辑
        }
    }
}

3. 通用Manifest获取逻辑

不管是文件系统中的JAR还是Tomcat中的资源JAR,都可通过JarInputStream读取Manifest,注意使用Java 8支持的try-with-resources语法自动关闭流,避免资源泄漏。

注意事项

  • 确保代码兼容Java 8:避免使用Java 9+的API,所有IO操作使用try-with-resources
  • Tomcat中获取的JAR资源是通过URL访问的,不能直接用File类处理,必须通过InputStream读取
  • 若需处理WEB-INF/classes目录下的MANIFEST.MF,可单独通过ServletContext获取该资源进行读取

内容的提问来源于stack exchange,提问作者Szdnez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 05:05:22