Gradle 多模块项目实现 Maven Parent 继承方式
2017-09-19 11:12
736 查看
目录
背景介绍
环境、软件准备
Gradle 安装
Gradle 多模块项目搭建
类似 Maven Parent 继承方式实现
FAQ
1、背景介绍
Gradle 是基于 JVM 的构建工具,是基于 Ant 、Maven、ivy 概念的一款通用灵活的构建工具,基于 Groovy 脚本构建,目前支持 Java、Groovy、Kotlin 和 Scala 语言,能够满足日常开发中复杂构建需求的开源工具。
好了,介绍了那么多Gradle,切入正题。最近一直在研究 Gradle 的使用配置,感觉 Gradle 对比下 Maven 还是挺好用的,刚好公司有项目组开始尝试 Maven 转 Gradle,碰到的第一个难题就如标题了。 对于 Muti-project 项目,Gradle 也提供了很好的支持,通过配置 allprojects 和 subprojects 能够很好的在父项目与子模块之间中配置依赖和继承。但是,对于多个 Muti-project 都需要依赖某些插件的时候,在用这种方式就不友好了,我们会想起 Maven 工程中 Parent 继承父 POM 的方式,就可以把一些通用的插件配置集中配置,其他项目使用,直接 Parent 指定 POM 版本方式,就可以直接继承使用,岂不是很方便。。。
仔细扒了下 Gradle 官方文档,以及 Google 类似问题,多数提供的解决方案是自定义插件,虽然说通过 Gradle 自定义插件可以实现,但是对于我们要在通用插件中还需要使用别人写好的插件的时候,或者说别人插件并不能完全满足需求,我们还需要在此基础上做一些扩展 Task 的时候,这个自定义插件就不是那么简单的写出来了。我们需要的是 在 common.gradle 中直接定义使用别人的插件或者在增加一些扩展 Task 来满足需求,项目需要使用的时候,直接继承 common.gradle 就能使用定义的 Task,类似 Maven Parent 继承方式。
2、环境、软件准备
本次演示环境,我是在本机 Mac OX 上操作,以下是安装的软件及版本:
Gradle:version 4.1
Java: version 1.8.0_91
gradle-release-plugin:2.4.0
注意:这里我们要演示下 Java Gradle 项目使用 gradle-release 插件执行 release 版本管理操作,所以需要先安装一下 Java、Gradle。Java 这里忽略安装过程。
3、Gradle 安装
Gradle 安装方式有好几种,这里介绍下本地 Mac OX 上 Homebrew 安装和 Linux 上源码安装:
1、Homebrew 安装和升级
2、Linux 源码安装
2.1 官网下载 gradle-4.1 源码包
2.2 解压缩源码包到指定目录
2.3 配置系统环境变量
配置完成后,使用
4、Gradle 多模块项目搭建
4.1 创建 Muti-project 项目
首先创建项目 gradle_demo,并初始化 gradle。
然后创建两个子模块,分别为 api 和 web,这里 api 我们打包成 jar,web 打包成 war,以示区别。
4.2 修改各模块配置
首先修改父目录下 settings.gradle,配置子模块:
然后修改父目录下 build.gradle,配置子模块通用依赖
接着修改子模块 api/build.gradle 定义 api 模块的其他依赖和配置
最后修改子模块 web/build.gradle 定义 web 模块的其他依赖和配置
配置完成后,执行
执行
执行
5、类似 Maven Parent 继承方式实现
这里我们先在父项目根目录新建一个 common.gradle 的通用配置文件,配置一些我们依赖的其他插件,这里就以 gradle-release 和 java 插件为例,演示 release 版本管理操作以及 upload war | jar 到自定义 Nexus 服务地址上。
注意:
1、这里我们使用了第三方插件 gradle-release:2.4.0 和官方 java 插件。
2、gradle-release 插件默认 Task release,可配置很多参数,详情可参考 GitHub gradle-release 配置使用。
3、配置
4、
5、Task uploadArchives 这里配置了本地 Nexus 服务地址,Nexus 服务搭建可参照之前文章Java Maven项目之Nexus私服搭建和版本管理应用 搭建。
好了,关键点来了,子模块如何使用 common.gradle 通用配置文件里面配置好的 Task呢?命令就是
很简单,只需要一两步即可。不过大致分为两种情况:
第一种:所有模块都执行,那么只修改父项目根目录下 build.gradle 配置如下:
这样所有的子模块包括父项目都可以使用 common.gradle 里面配置好的 Task 了。当我们执行
那么问题来了,有人会问,如果我下边的子项目例如 rpc 模块,它是一个基础服务,它不使用该插件,这样执行会强制执行了 release 操作啦,再或者例如 api 模块,它不需要执行 release,再或者父项目只需要执行 release 不需要执行 upload 等等。
像这种问题,也可以解决掉,一种方式是启动时指定子模块或者父模块。
另一种方式是,配置
第二种方式:指定模块执行方式,修改父项目根目录下 build.gradle 以及指定模块目录下 ${subMOdule}/build.gradle
注意:这里我设置 api 模块不继承 common.gradle,web 模块继承,父模块不继承只定义了 release 插件。
这样一来,在执行
具体 gradle-release 以及 java uploadArchives 插件操作效果这里就不截图演示了。跟 Java Maven项目之Nexus私服搭建和版本管理应用 文章后半部分版本管理应用功能类似。
6、FAQ
6.1 配置完 Muti-project 后,会去自动下载 https://services.gradle.org/distributions/gradle-{version}-all.zip,没有网络或者内网时下载不下来。解决办法如下:
6.2 配置使用第三方插件有两种方式,当在 common.gradle 中,使用
这个 gradle 规定就是这样的,期待以后支持吧。解决办法就是换成如下方式:
6.3 在 common.gradle 中已经定义了
这个需要在父模块根目录 build.gradle 中再次指定一下
==========================这里是分界线==========================
经过再次测试,发现也可在父模块根目录 build.gradle 中不指定
注意:
参考资料
Gradle Userguide
Gradle Install
GitHub gradle-release
背景介绍
环境、软件准备
Gradle 安装
Gradle 多模块项目搭建
类似 Maven Parent 继承方式实现
FAQ
1、背景介绍
Gradle 是基于 JVM 的构建工具,是基于 Ant 、Maven、ivy 概念的一款通用灵活的构建工具,基于 Groovy 脚本构建,目前支持 Java、Groovy、Kotlin 和 Scala 语言,能够满足日常开发中复杂构建需求的开源工具。
好了,介绍了那么多Gradle,切入正题。最近一直在研究 Gradle 的使用配置,感觉 Gradle 对比下 Maven 还是挺好用的,刚好公司有项目组开始尝试 Maven 转 Gradle,碰到的第一个难题就如标题了。 对于 Muti-project 项目,Gradle 也提供了很好的支持,通过配置 allprojects 和 subprojects 能够很好的在父项目与子模块之间中配置依赖和继承。但是,对于多个 Muti-project 都需要依赖某些插件的时候,在用这种方式就不友好了,我们会想起 Maven 工程中 Parent 继承父 POM 的方式,就可以把一些通用的插件配置集中配置,其他项目使用,直接 Parent 指定 POM 版本方式,就可以直接继承使用,岂不是很方便。。。
仔细扒了下 Gradle 官方文档,以及 Google 类似问题,多数提供的解决方案是自定义插件,虽然说通过 Gradle 自定义插件可以实现,但是对于我们要在通用插件中还需要使用别人写好的插件的时候,或者说别人插件并不能完全满足需求,我们还需要在此基础上做一些扩展 Task 的时候,这个自定义插件就不是那么简单的写出来了。我们需要的是 在 common.gradle 中直接定义使用别人的插件或者在增加一些扩展 Task 来满足需求,项目需要使用的时候,直接继承 common.gradle 就能使用定义的 Task,类似 Maven Parent 继承方式。
2、环境、软件准备
本次演示环境,我是在本机 Mac OX 上操作,以下是安装的软件及版本:
Gradle:version 4.1
Java: version 1.8.0_91
gradle-release-plugin:2.4.0
注意:这里我们要演示下 Java Gradle 项目使用 gradle-release 插件执行 release 版本管理操作,所以需要先安装一下 Java、Gradle。Java 这里忽略安装过程。
3、Gradle 安装
Gradle 安装方式有好几种,这里介绍下本地 Mac OX 上 Homebrew 安装和 Linux 上源码安装:
1、Homebrew 安装和升级
$ brew update && brew install gradle //安装 $ brew upgrade gradle // 升级
2、Linux 源码安装
2.1 官网下载 gradle-4.1 源码包
2.2 解压缩源码包到指定目录
$ mkdir /opt/gradle $ unzip -d /opt/gradle gradle-4.1-bin.zip
2.3 配置系统环境变量
$ export PATH=$PATH:/opt/gradle/gradle-4.1/bin
配置完成后,使用
gradle -v查看是否安装成功。注意:gradle 运行环境依赖 JKD | JRE 版本需要 >= 1.7。
4、Gradle 多模块项目搭建
4.1 创建 Muti-project 项目
首先创建项目 gradle_demo,并初始化 gradle。
mkdir gradle_demo && cd gradle_demo gradle init
然后创建两个子模块,分别为 api 和 web,这里 api 我们打包成 jar,web 打包成 war,以示区别。
mkdir -p api/src/main/java mkdir -p api/src/test/java mkdir -p web/src/main/java mkdir -p web/src/test/java mkdir -p web/src/main/resources mkdir -p web/src/main/webapp
4.2 修改各模块配置
首先修改父目录下 settings.gradle,配置子模块:
include 'api','web'
然后修改父目录下 build.gradle,配置子模块通用依赖
//子模块配置 subprojects { apply plugin: 'java' apply plugin: 'maven' apply plugin: "idea" ext { junitVersion = "4.11" springVersion = "4.3.3.RELEASE" jacksonVersion = "2.4.4" compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = 'UTF-8' } sourceCompatibility = 1.8 targetCompatibility = 1.8 tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } //配置依赖 dependencies { compile( "org.springframework:spring-webmvc:${springVersion}", "org.springframework:spring-jdbc:${springVersion}", "org.springframework:spring-web:${springVersion}", "org.springframework:spring-oxm:${springVersion}", "org.springframework:spring-context-support:${springVersion}", "com.mangofactory:swagger-springmvc:1.0.2", "com.fasterxml.jackson.core:jackson-annotations:${jacksonVersion}", "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}", "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}", "javax.mail:mail:1.4.7", "org.slf4j:slf4j-api:1.7.10", "org.slf4j:slf4j-log4j12:1.7.10", "log4j:log4j:1.2.17" ) testCompile("junit:junit:${junitVersion}") } }
接着修改子模块 api/build.gradle 定义 api 模块的其他依赖和配置
apply plugin: 'application' group = "com.gradle.api" version = "${rootProject.version}" //也可以不写,默认继承父模块 version description = "this is gradle api demo" archivesBaseName = 'gradle_api' mainClassName = "com.gradle.api.Main" //指定 Jar 启动 Main
最后修改子模块 web/build.gradle 定义 web 模块的其他依赖和配置
apply plugin: 'war' group = "com.gradle.web" version = "${rootProject.version}" //也可以不写,默认继承父模块 version description = "this is gradle web demo" archivesBaseName = 'gradle_web' //如果依赖子模块 api 时配置,若配置,则 build 该子模块时同时 build 依赖的子模块。 dependencies{ compile project(":api") }
配置完成后,执行
gradle build即可 build 所有模块。
执行
gradle tasks --all查看所有的 Task 列表。
执行
gradle api:build只 build api 模块,执行
gradle web:build会先 build api,然后 build web,这是因为 web 配置了依赖 api 模块
compile project(":api")。
5、类似 Maven Parent 继承方式实现
这里我们先在父项目根目录新建一个 common.gradle 的通用配置文件,配置一些我们依赖的其他插件,这里就以 gradle-release 和 java 插件为例,演示 release 版本管理操作以及 upload war | jar 到自定义 Nexus 服务地址上。
buildscript { repositories { jcenter() } dependencies { classpath 'net.researchgate:gradle-release:2.4.0' // release plugin } } apply plugin: 'java' apply plugin: 'maven' apply plugin: 'idea' apply plugin: 'net.researchgate.release' ext { civersion = System.getProperty("ci-version") ?: "${project.version}" maven_username = System.env.maven_username maven_password = System.env.maven_password } sourceCompatibility = 1.8 targetCompatibility = 1.8 tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } //upload war | jar to nexus uploadArchives { repositories { mavenDeployer { repository(url: "http://127.0.0.1:9998/nexus/content/repositories/releases") { authentication(userName: "${maven_username}", password: "${maven_password}") } pom.version = "${civersion}" pom.artifactId = "${project.archivesBaseName}" pom.groupId = "${project.group}" } } } //config release task release { tagCommitMessage = "[Gradle Release Plugin] - creating tag: " scmAdapters = [ net.researchgate.release.GitAdapter, ] } //当需要 relase Task 之前执行 upload 操作时配置依赖 //afterReleaseBuild.dependsOn uploadArchives
注意:
1、这里我们使用了第三方插件 gradle-release:2.4.0 和官方 java 插件。
2、gradle-release 插件默认 Task release,可配置很多参数,详情可参考 GitHub gradle-release 配置使用。
3、配置
civerison变量可接受命令行参数
-Dci-version=${ci_version}形式传递,若不传默认取项目的 version,这里因为子模块都继承了父项目 version,能达到版本统一管理。
4、
maven_username和
maven_password变量这里通过获取系统环境变量的方式获取。也可以通过命令行参数获取,还可以通过 gradle.properties 配置获取。
5、Task uploadArchives 这里配置了本地 Nexus 服务地址,Nexus 服务搭建可参照之前文章Java Maven项目之Nexus私服搭建和版本管理应用 搭建。
pom.version = "${civersion}"这里取
civersion变量,目的也是为了达到版本统一管理的目的。
好了,关键点来了,子模块如何使用 common.gradle 通用配置文件里面配置好的 Task呢?命令就是
apply from {path_common.gradle } | {http_common.gradle }
很简单,只需要一两步即可。不过大致分为两种情况:
第一种:所有模块都执行,那么只修改父项目根目录下 build.gradle 配置如下:
//获取 common.gradle 依赖插件配置 buildscript { repositories { jcenter() } dependencies { classpath 'net.researchgate:gradle-release:2.4.0' // release plugin } } //所有模块配置 allprojects { apply from: "${rootProject.projectDir}/common.gradle" }
这样所有的子模块包括父项目都可以使用 common.gradle 里面配置好的 Task 了。当我们执行
gradle release时,那么父项目以及子项目都会执行 release 操作了。是不是类似 Maven Parent 继承方式了。
那么问题来了,有人会问,如果我下边的子项目例如 rpc 模块,它是一个基础服务,它不使用该插件,这样执行会强制执行了 release 操作啦,再或者例如 api 模块,它不需要执行 release,再或者父项目只需要执行 release 不需要执行 upload 等等。
像这种问题,也可以解决掉,一种方式是启动时指定子模块或者父模块。
gradle release // 执行所有模块 gradle :release // 只执行父模块 gradle web:release // 只执行 web 子模块 gradle web:release api:release //只执行 web、api子模块
另一种方式是,配置
apply from: "${rootProject.projectDir}/common.gradle"到指定子模块的 build.gradle 文件中,这样就只有该子模块可使用通用配置了。
第二种方式:指定模块执行方式,修改父项目根目录下 build.gradle 以及指定模块目录下 ${subMOdule}/build.gradle
1、修改父项目根目录下 build.gradle //获取 common.gradle 依赖插件配置 buildscript { repositories { jcenter() } dependencies { classpath 'net.researchgate:gradle-release:2.4.0' // release plugin } } apply plugin: 'java' apply plugin: 'net.researchgate.release' //指定父项目也可以使用 release 插件,不指定则父项目不可使用 release 插件。 //所有模块配置 allprojects { //配置仓库地址,以及第三方包地址( public 中找不到时,从 thirdparty 中找) repositories { maven { url "http://127.0.0.1:9998/nexus/content/groups/public" artifactUrls "http://127.0.0.1:9998/nexus/content/repositories/thirdparty" } } } 2、修改 web 模块,web/build.gradle 增加配置: apply from: "${rootProject.projectDir}/common.gradle"
注意:这里我设置 api 模块不继承 common.gradle,web 模块继承,父模块不继承只定义了 release 插件。
这样一来,在执行
gradle release就执行父模块以及 web 模块了。如果父项目不配置使用release 插件,则执行
gradle release就只执行 web 模块了。当然,执行
gradle web:release还是会只执行 web 模块的。
具体 gradle-release 以及 java uploadArchives 插件操作效果这里就不截图演示了。跟 Java Maven项目之Nexus私服搭建和版本管理应用 文章后半部分版本管理应用功能类似。
6、FAQ
6.1 配置完 Muti-project 后,会去自动下载 https://services.gradle.org/distributions/gradle-{version}-all.zip,没有网络或者内网时下载不下来。解决办法如下:
1、到 ~/.gradle/wrapper/dists/gradle-{version}-all/ 下边,不规则命名的文件夹下边找到gradle-{version}-all.zip。 2、去指定网址下载该版本的 gradle-{version}-all.zip。 将 gradle-{version}-all.zip 拷贝到该项目根目录 gradle/wrapper/ 下,并修改 gradle-wrapper.properties 配置,将 distributionUrl 修改为 distributionUrl=gradle-{version}-bin.zip 就可以了。
6.2 配置使用第三方插件有两种方式,当在 common.gradle 中,使用
plugins { ... }方式时,子模块使用
apply from {path_common.gradle } | {http_common.gradle }时,会报错
* What went wrong: Could not compile script '/Users/wanyang3/git/gradle_demo/common.gradle'. > startup failed: script '/Users/wanyang3/git/gradle_demo/common.gradle': 10: Only Project build scripts can contain plugins {} blocks See https://docs.gradle.org/4.1/userguide/plugins.html#sec:plugins_block for information on the plugins {} block @ line 10, column 1. plugins { ^ 1 error
这个 gradle 规定就是这样的,期待以后支持吧。解决办法就是换成如下方式:
buildscript { repositories { jcenter() } dependencies { classpath 'net.researchgate:gradle-release:2.4.0' // release plugin } } apply plugin: 'net.researchgate.release'
6.3 在 common.gradle 中已经定义了
buildscript { ... }依赖插件,在父模块根目录 build.gradle 中不在指定
buildscript { ... },会报错:
* What went wrong: A problem occurred evaluating root project 'gradle_demo'. > Plugin with id 'net.researchgate.release' not found.
这个需要在父模块根目录 build.gradle 中再次指定一下
buildscript { ... }依赖插件就行。
==========================这里是分界线==========================
经过再次测试,发现也可在父模块根目录 build.gradle 中不指定
buildscript { ... }依赖插件,也可以直接使用 common.gradle 定义的插件,方法就是:
修改 common.gradle buildscript { repositories { jcenter() } dependencies { classpath 'net.researchgate:gradle-release:2.4.0' // release plugin } } //apply plugin: 'net.researchgate.release' //注释掉,不使用此方式。 // 正解如下方式添加插件 if (!project.plugins.findPlugin(net.researchgate.release.ReleasePlugin)) project.apply(plugin: net.researchgate.release.ReleasePlugin)
注意:
net.researchgate.release.ReleasePlugin这个是插件的主函数,可在该插件 GitHub 项目源码 src/main/resources/META-INF/gradle-plugins/net.researchgate.release.properties 文件中找到
implementation-class=net.researchgate.release.ReleasePlugin,应用其他插件方式同上即可。
参考资料
Gradle Userguide
Gradle Install
GitHub gradle-release
相关文章推荐
- Maven工程多模块继承和聚合项目创建与数据库测试步骤详解
- Springboot整合dubbo构建maven多模块项目(三) - 把server分为api(服务接口定义)和server(服务实现)两个子module
- myeclipse+maven实现多模块项目struts+spring+mybatis,详解
- Maven之Parent模块配置-关于聚合与继承、依赖管理、占位符、构建管理和多套环境
- Maven多模块项目 eclipse热部署 Maven项目实现 tomcat热部署 .
- Maven系列五:多模块项目中的聚合和继承
- Maven多模块项目 eclipse暖部署 Maven项目实现 tomcat热部署
- 基于Maven的SpringBoot项目实现热部署的两种方式
- myeclipse+maven实现多模块项目struts+spring+mybatis
- Maven 多模块项目 实现
- 基于Maven的SpringBoot项目实现热部署的两种方式
- Maven多模块项目 eclipse热部署 Maven项目实现 tomcat热部署
- [置顶] Maven多模块项目 eclipse热部署 Maven项目实现 tomcat热部署 二
- myeclipse+maven实现多模块项目struts+spring+mybatis
- eclipse +maven实现多模块项目struts+spring+mybatis
- Maven多模块项目 eclipse热部署 Maven项目实现 tomcat热部署
- 【Maven进阶二】多模块构建Maven项目-Dos命令实现
- Maven多模块项目 eclipse热部署 Maven项目实现 tomcat热部署 .
- Maven 的聚合(多模块)和 Parent 继承
- myeclipse+maven实现多模块项目struts+spring+mybatis,详解