读取MANIFEST.MF中Bundle-SymbolicName的值

本文介绍了一种从MANIFEST.MF文件中读取Bundle-SymbolicName及其版本的方法。通过提供的Java代码,可以解析.jar文件并获取指定的元数据。
    /**
* Function :readManifestContext
* <p>
* Description :读取MANIFEST.MF中Bundle-SymbolicName的值
* <p>
* Author 2009-3-17
* @param filePath
* 文件路径
* @return
* @throws Exception
*/
public static String getBundleSymbolicNameAndVersion(String filePath)
{
if (filePath == null || filePath.equals("")
|| !filePath.endsWith(".jar"))
{
return null;
}

try
{
JarFile jf = new JarFile(filePath);
Manifest mf = jf.getManifest();
Attributes attributes = mf.getMainAttributes();
String bundleSymbolicName = attributes
.getValue(BUNDLE_SYMBOLIC_NAME);
if (bundleSymbolicName != null && !bundleSymbolicName.equals(""))
{
bundleSymbolicName = bundleSymbolicName.split(";")[0];
if (bundleSymbolicName != null
&& !bundleSymbolicName.equals(""))
{
String bundleVersion = attributes.getValue(BUNDLE_VERSION);
return bundleSymbolicName
+ (bundleVersion == null ? "" : " ("
+ bundleVersion + ") ");
}
}
return null;
}
catch (IOException e)
{
return null;
}
}
Jetty 是一个基于 Java 的 Web 服务器和 Servlet 容器,它在部署 Web 应用(WAR 或 JAR)时会解析 `MANIFEST.MF` 文件。如果 `MANIFEST.MF` 中包含 `Class-Path` 属性,Jetty 会根据该属性加载额外的类路径资源。这种机制原本是 Java 标准的 JAR 文件规范的一部分,但在某些场景下(如 Spring Boot 的嵌套 JAR 结构)可能会导致问题。 --- ## ✅ Jetty 解析 `MANIFEST.MF` 中 `Class-Path` 的流程 ### 1. `MANIFEST.MF` 示例 ```plaintext Manifest-Version: 1.0 Class-Path: lib/commons-lang3-3.12.0.jar lib/guava-30.1-jre.jar Main-Class: com.example.Main ``` 在这个例子中,`Class-Path` 指定了两个依赖 JAR 包。 --- ### 2. Jetty 解析 `Class-Path` 的核心类 Jetty 通过 `WebAppClassLoader` 和 `WebAppContext` 来处理类加载,具体流程如下: #### 核心类: - `org.eclipse.jetty.webapp.WebAppClassLoader`:Jetty 的 Web 应用类加载器 - `org.eclipse.jetty.webapp.ManifestOrdering`:用于控制是否启用 `Class-Path` 的解析 - `org.eclipse.jetty.util.Manifest`:工具类,用于读取和解析 MANIFEST 文件 --- ### 3. Jetty 如何解析 `Class-Path` #### 步骤说明: 1. **加载 WAR 或 JAR 文件** - Jetty 会将 Web 应用打包成 WAR 或嵌套 JAR 文件 - 在部署时,Jetty 会解析该文件中的 `META-INF/MANIFEST.MF` 2. **读取 `Class-Path` 属性** - 如果 `MANIFEST.MF` 中存在 `Class-Path` 条目,则会提取这些路径 - 这些路径是相对于 JAR 文件根目录的相对路径或绝对路径 3. **构建 URL 列表** - Jetty 会将 `Class-Path` 中的路径转换为 `URL` 列表 - 如果是 WAR 文件,Jetty 会将这些路径映射为文件系统或 JAR 内的路径 4. **添加到 ClassLoader** - Jetty 会将这些 URL 添加到 `WebAppClassLoader` 中 - 这样 Web 应用就可以通过类加载器加载这些 JAR 中的类 --- ### 4. Jetty 的配置选项控制 `Class-Path` 解析 你可以通过以下方式控制是否解析 `Class-Path`: #### ✅ 方法一:使用 JVM 参数禁用 ```bash java -Djetty.ignoreManifestClassPath=true -jar your-app.jar ``` - 该参数会告诉 Jetty 忽略所有 `MANIFEST.MF` 中的 `Class-Path` 条目 #### ✅ 方法二:在代码中设置属性 ```java context.setAttribute("org.eclipse.jetty.webapp.ManifestOrdering", false); ``` - 这个属性控制是否启用 `MANIFEST.MF` 中的 `Class-Path` 解析 --- ## ✅ 示例:手动解析 MANIFEST.MF 中的 Class-Path 如果你需要手动解析 `MANIFEST.MF`,可以使用如下代码: ```java import org.eclipse.jetty.util.Manifest; import java.io.InputStream; import java.net.URL; import java.util.List; public class ManifestParser { public static void main(String[] args) throws Exception { URL manifestUrl = new URL("jar:file:/path/to/your.jar!/META-INF/MANIFEST.MF"); try (InputStream is = manifestUrl.openStream()) { Manifest manifest = new Manifest(is); List<String> classPathEntries = manifest.getClassPath(); System.out.println("Class-Path entries:"); for (String entry : classPathEntries) { System.out.println(entry); } } } } ``` --- ## ✅ 为什么 Spring Boot 需要跳过 Class-Path? Spring Boot 使用的是 **嵌套 JAR(fat jar)** 结构,其依赖被打包在 `BOOT-INF/lib` 目录下。而标准的 Java `Class-Path` 机制无法识别这种嵌套结构。 如果 Jetty 解析了 `MANIFEST.MF` 中的 `Class-Path`,可能会导致: - 类加载失败(路径不存在) - 类重复加载(与 Spring Boot 的类加载器冲突) - 安全隐患(加载了不该加载的库) --- ## ✅ 总结解释 | 步骤 | 描述 | |------|------| | 1. 读取 MANIFEST.MF | Jetty 从 WAR 或 JAR 中读取 MANIFEST 文件 | | 2. 提取 Class-Path | 如果存在 Class-Path 属性,提取其 | | 3. 转换为 URL | 将路径转换为可加载的 URL 列表 | | 4. 加入 ClassLoader | 将这些 URL 添加到 WebAppClassLoader | | 5. 控制机制 | 可通过 JVM 参数或 context.setAttribute 控制是否启用 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值