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

Maven Shade Plugin:如何在MANIFEST中保留依赖Jar版本?

解决Maven Shade打Fat Jar时依赖版本获取异常的问题

用Shade插件打可执行Fat Jar时,依赖通过ClassName.class.getPackage().getImplementationVersion()拿自身版本,结果拿到的是应用版本——这是因为Shade把所有依赖的内容合并到顶层Jar,原依赖的MANIFEST被覆盖了。你之前硬编码依赖版本到MANIFEST的办法会丢失应用版本,试试下面几个更优的方案:

方案1:保留依赖原MANIFEST,单独读取

让Shade插件保留目标依赖的MANIFEST文件(重命名避免冲突),然后在代码里直接读这个文件拿版本,顶层MANIFEST保留应用版本。

修改Shade插件配置:

<transformers>
  <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
    <manifestEntries>
      <mainClass>path.to.main.class</mainClass>
      <Implementation-Version>${project.version}</Implementation-Version> <!-- 保留应用版本 -->
      <Specification-Version>${project.version}</Specification-Version>
    </manifestEntries>
  </transformer>
  <!-- 把目标依赖的MANIFEST重命名后保留,避免和顶层冲突 -->
  <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
    <resource>META-INF/MANIFEST-${dependency.groupId}-${dependency.artifactId}.MF</resource>
  </transformer>
</transformers>

代码里读取依赖版本:

InputStream manifestStream = Thread.currentThread().getContextClassLoader()
    .getResourceAsStream("META-INF/MANIFEST-${dependency.groupId}-${dependency.artifactId}.MF");
Manifest manifest = new Manifest(manifestStream);
String dependencyVersion = manifest.getMainAttributes().getValue("Implementation-Version");

方案2:给依赖包单独注入版本信息

用Shade的PackageResourceTransformer给目标依赖的根包单独设置版本属性,这样依赖调用getImplementationVersion()时拿到的是自身版本,应用类拿到的还是顶层MANIFEST里的应用版本。

配置示例:

<transformers>
  <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
    <manifestEntries>
      <mainClass>path.to.main.class</mainClass>
      <Implementation-Version>${project.version}</Implementation-Version> <!-- 保留应用版本 -->
      <Specification-Version>${project.version}</Specification-Version>
    </manifestEntries>
  </transformer>
  <!-- 给目标依赖的根包设置版本 -->
  <transformer implementation="org.apache.maven.plugins.shade.resource.PackageResourceTransformer">
    <package>com.example.dependency.package</package> <!-- 替换成依赖的实际根包 -->
    <implementationVersion>${dependency.version}</implementationVersion> <!-- 依赖版本,直接用pom里的变量 -->
    <specificationVersion>${dependency.version}</specificationVersion>
  </transformer>
</transformers>

方案3:在顶层MANIFEST中同时保留两个版本

如果需要在同一个MANIFEST里存应用和依赖版本,加自定义属性就行,代码里按需读取。

配置:

<transformers>
  <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
    <manifestEntries>
      <mainClass>path.to.main.class</mainClass>
      <Implementation-Version>${project.version}</Implementation-Version> <!-- 应用版本 -->
      <Specification-Version>${project.version}</Specification-Version>
      <Dependency-Implementation-Version>${dependency.version}</Dependency-Implementation-Version> <!-- 依赖版本 -->
    </manifestEntries>
  </transformer>
</transformers>

代码里读取:

// 拿应用版本
String appVersion = getClass().getPackage().getImplementationVersion();
// 拿依赖版本
InputStream manifestStream = getClass().getClassLoader().getResourceAsStream("META-INF/MANIFEST.MF");
Manifest manifest = new Manifest(manifestStream);
String dependencyVersion = manifest.getMainAttributes().getValue("Dependency-Implementation-Version");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 05:07:44