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

