如何在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
相关产品推荐
相关产品推荐

