Gradle 打包依赖为 fatJar 添加源码上传到 Maven

2024-02-21 10:18

本文主要是介绍Gradle 打包依赖为 fatJar 添加源码上传到 Maven,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文记录内容:Gradle 编译,打 jar 包的时候如果遇到有依赖库只有本地 jar 包,不提供在线仓库依赖的时候,如何把所有依赖打包在一起,附带自己的源码一起上传到 maven 仓库

Gradle: 4.10
Java: 1.8

1. 合并本地依赖 jar 包,打包出 fatJar

1.1 首先贴一下项目结构


buildscript {ext {nexusConfig = ["repository"      : "https://repo.xxxx","uploaderName"    : "xxx","uploaderPassword": "xxxxxx","readerName"      : "xxx","readerPassword"  : "xxxxxx"]}dependencies {classpath "com.github.jengelman.gradle.plugins:shadow:4.0.4"}repositories {jcenter()}
}subprojects {apply plugin: 'java'sourceCompatibility = 1.8group 'com.xxxx.xxxxxx'repositories {jcenter()mavenCentral()flatDir { dirs 'libs' }maven {url nexusConfig.repositorycredentials {username nexusConfig.readerNamepassword nexusConfig.readerPassword}}}dependencies {testImplementation 'junit:junit:4.12'}
}

Project 配置文件


version '1.1.2'
description 'xiaomi push service'dependencies {implementation fileTree('libs')
}apply from: "../publish.gradle"
apply from: "../shadow.gradle"

如上, 这是一个使用小米推送的服务端业务封装库,小米只提供了本地 jar 包,需要打包在一起供其他项目依赖。

1.2 使用 Shadow 插件打 fatJar

插件地址

shadow.gradle 的内容


apply plugin: 'com.github.johnrengelman.shadow'shadowJar {// 完整名称为 baseName-version-classifier.jarbaseName = project.name// 默认为 '-all' 为 null 则去除该参数classifier = nullversion = project.version// 方法数超过 65535 会报错, 需要打开下面这个配置//zip64 = true// 去除和添加文件 META-INF// include '.... 文件'// exclude '... 文件'// 如果有 Main 函数, 如下配置启动类//manifest {//    attributes 'Main-Class': 'com.example.Main'//}
}sourcesJar.dependsOn(shadowJar)

1.3 Shadow 打包原理

打 fatJar 有好几种方式,Shadow 用的是第二种

  1. 解压所有 jar,重新压缩合并在一个 jar 中
  2. 不合并,只是把依赖 jar 移动到最终 jar 包的 lib 目录下,然后在 manifest 中把 class-path 指向这个地址,那么加载类时就能正确找到
  3. 嵌套 jars, SpringBoot Gradle plugin 在用,需要用它的启动器自定义 ClassLoader 来启动,会加入很多业务无关代码

优点

  • 结构和原理简单
  • 不会有无关代码

缺点

  • 类文件路径被改了, 因此如果有直接调用 Class 文件名字或路径进行类加载的代码,会报错

1.4 Shadow 实现

插件会创建 2 个 task, shadowJar 负责打包, uploadShadow 负责上传 Maven,核心代码就是下面这一段了

protected void configureShadowTask(Project project) {JavaPluginConvention convention = project.convention.getPlugin(JavaPluginConvention)ShadowJar shadow = project.tasks.create(SHADOW_JAR_TASK_NAME, ShadowJar)shadow.group = SHADOW_GROUPshadow.description = 'Create a combined JAR of project and runtime dependencies'shadow.conventionMapping.with {map('classifier') {'all'}}if (GradleVersion.current() >= GradleVersion.version("5.1")) {shadow.archiveClassifier.set("all")}shadow.manifest.inheritFrom project.tasks.jar.manifestshadow.doFirst {def files = project.configurations.findByName(ShadowBasePlugin.CONFIGURATION_NAME).filesif (files) {def libs = [project.tasks.jar.manifest.attributes.get('Class-Path')]libs.addAll files.collect { "${it.name}" }manifest.attributes 'Class-Path': libs.findAll { it }.join(' ')}}shadow.from(convention.sourceSets.main.output)shadow.configurations = [project.configurations.findByName('runtimeClasspath') ?project.configurations.runtimeClasspath : project.configurations.runtime]shadow.exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'module-info.class')project.artifacts.add(ShadowBasePlugin.CONFIGURATION_NAME, shadow)configureShadowUpload()}private void configureShadowUpload() {configurationActionContainer.add(new Action<Project>() {void execute(Project project) {project.plugins.withType(MavenPlugin) {Upload upload = project.tasks.withType(Upload).findByName(SHADOW_UPLOAD_TASK)if (!upload) {return}upload.configuration = project.configurations.shadowMavenPom pom = upload.repositories.mavenDeployer.pompom.scopeMappings.mappings.remove(project.configurations.compile)pom.scopeMappings.mappings.remove(project.configurations.runtime)pom.scopeMappings.addMapping(MavenPlugin.RUNTIME_PRIORITY, project.configurations.shadow, Conf2ScopeMappingContainer.RUNTIME)}}})}

上面的代码就是配置 task 实现了 jar 包位置替换, 指定 Class-Path,移除多余文件,去除 Maven 中的打包任务替换为自己的然后上传

更多代码看 GitHub

2. 上传源码到 Maven

按照第一节的内容,已经完成了打包 fatJar 并上传 Maven 的操作,但我发现使用 uploadShadow 这个 Shadow 插件自带的 task 上传的 jar 包里,不带源码!不爽,看看能不能改进。

2.1 不使用 uploadShadow 任务,但调用 shadowJar 任务做打包

实现方案如上述标题,默认的 Maven 插件提供的 task 中会调用 jar 这个 task 进行打包,如果有指定源码,那么也会同步上传源码,uploadShadow 中把实现给替换了,但没有写入上传源码的操作,就算打出源码也不会上传,所以换种思路。


apply plugin: 'maven'task sourcesJar(type: Jar) {classifier = 'sources'from sourceSets.main.java.srcDirs
}artifacts {archives sourcesJar
}// 如果希望 gradle install,安装到. m2 本地仓库,参考下面的内容
install {repositories.mavenInstaller {pom.project {version project.versionartifactId project.namegroupId project.grouppackaging 'jar'description project.description}}
}uploadArchives {configuration = configurations.archivesrepositories {mavenDeployer {repository(url: nexusConfig.repository) {authentication(userName: nexusConfig.uploaderName,password: nexusConfig.uploaderPassword)}snapshotRepository(url: nexusConfig.repositorySnapshot) {authentication(userName: nexusConfig.snapshotName,password: nexusConfig.snapshotPassword)}pom.project {version project.versionartifactId project.namegroupId project.grouppackaging 'jar'description project.description}}}
}

上面这个 publish.gradle 是无 shadow 依赖的, 只是加入一个全局的 sourceJar 任务用来生成源码。

configurations.archives 是 uploadArchives 任务的默认实现,会上传源码,因此我们只要让 sourceJar 和 shadowJar 这 2 个任务都运行一遍就可以了。

只要 shadow.gradle 在 publish.gradle 之后加载,它就能拿到 publish.gradle 中定义的 sourceJar 任务,并指定这个任务依赖 shadowJar 运行,uploadArchives 在进行编译源码操作时会连带先调用 shadowJar 编译 fatJar 替换掉 jar 任务的编译结果,最后一起上传,简单并解耦的实现了打包 fatJar 并带源码上传 Maven 的需求

apply from: "../publish.gradle"
apply from: "../shadow.gradle"

shadow.gradle

apply plugin: 'com.github.johnrengelman.shadow'shadowJar {.....
}sourcesJar.dependsOn(shadowJar)

3. 相同需求用Maven怎么做

Maven就是xml丑了点,其实配置很简单


<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.2.0</version><executions><execution><goals><goal>shade</goal></goals><configuration><transformers><transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><manifestEntries><Main-Class>${app.main.class}</Main-Class><X-Compile-Source-JDK>${maven.compile.source}</X-Compile-Source-JDK><X-Compile-Target-JDK>${maven.compile.target}</X-Compile-Target-JDK></manifestEntries></transformer></transformers></configuration></execution></executions></plugin><!-- 要将源码放上去,需要加入这个插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><configuration><attach>true</attach></configuration><executions><execution><!-- 将goal绑定到verify这个节点,可以避免每次compile代码时候都做打包源码 --><phase>verify</phase><goals><goal>jar</goal></goals></execution></executions></plugin></plugins></build>

替换${app.main.class}为你的main函数所在的类
${maven.compile.source}是你的项目源码的JDK版本如1.8
${maven.compile.target}是你的项目编译的Java版本如1.8

这篇关于Gradle 打包依赖为 fatJar 添加源码上传到 Maven的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/731432

相关文章

win10安装及配置Gradle全过程

《win10安装及配置Gradle全过程》本文详细介绍了Gradle的下载、安装、环境变量配置以及如何修改本地仓库位置,通过这些步骤,用户可以成功安装并配置Gradle,以便进行项目构建... 目录一、Gradle下载1.1、Gradle下载地址1.2、Gradle下载步骤二、Gradle安装步骤2.1、安

Python打包成exe常用的四种方法小结

《Python打包成exe常用的四种方法小结》本文主要介绍了Python打包成exe常用的四种方法,包括PyInstaller、cx_Freeze、Py2exe、Nuitka,文中通过示例代码介绍的非... 目录一.PyInstaller11.安装:2. PyInstaller常用参数下面是pyinstal

nodejs打包作为公共包使用的完整流程

《nodejs打包作为公共包使用的完整流程》在Node.js项目中,打包和部署是发布应用的关键步骤,:本文主要介绍nodejs打包作为公共包使用的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言一、前置准备二、创建与编码三、一键构建四、本地“白嫖”测试(可选)五、发布公共包六、常见踩坑提醒

python依赖管理工具UV的安装和使用教程

《python依赖管理工具UV的安装和使用教程》UV是一个用Rust编写的Python包安装和依赖管理工具,比传统工具(如pip)有着更快、更高效的体验,:本文主要介绍python依赖管理工具UV... 目录前言一、命令安装uv二、手动编译安装2.1在archlinux安装uv的依赖工具2.2从github

java 恺撒加密/解密实现原理(附带源码)

《java恺撒加密/解密实现原理(附带源码)》本文介绍Java实现恺撒加密与解密,通过固定位移量对字母进行循环替换,保留大小写及非字母字符,由于其实现简单、易于理解,恺撒加密常被用作学习加密算法的入... 目录Java 恺撒加密/解密实现1. 项目背景与介绍2. 相关知识2.1 恺撒加密算法原理2.2 Ja

Nginx屏蔽服务器名称与版本信息方式(源码级修改)

《Nginx屏蔽服务器名称与版本信息方式(源码级修改)》本文详解如何通过源码修改Nginx1.25.4,移除Server响应头中的服务类型和版本信息,以增强安全性,需重新配置、编译、安装,升级时需重复... 目录一、背景与目的二、适用版本三、操作步骤修改源码文件四、后续操作提示五、注意事项六、总结一、背景与

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

javacv依赖太大导致jar包也大的解决办法

《javacv依赖太大导致jar包也大的解决办法》随着项目的复杂度和依赖关系的增加,打包后的JAR包可能会变得很大,:本文主要介绍javacv依赖太大导致jar包也大的解决办法,文中通过代码介绍的... 目录前言1.检查依赖2.更改依赖3.检查副依赖总结 前言最近在写项目时,用到了Javacv里的获取视频

Vite 打包目录结构自定义配置小结

《Vite打包目录结构自定义配置小结》在Vite工程开发中,默认打包后的dist目录资源常集中在asset目录下,不利于资源管理,本文基于Rollup配置原理,本文就来介绍一下通过Vite配置自定义... 目录一、实现原理二、具体配置步骤1. 基础配置文件2. 配置说明(1)js 资源分离(2)非 JS 资

Spring 依赖注入与循环依赖总结

《Spring依赖注入与循环依赖总结》这篇文章给大家介绍Spring依赖注入与循环依赖总结篇,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. Spring 三级缓存解决循环依赖1. 创建UserService原始对象2. 将原始对象包装成工