第一章:Gradle 日志信息
1.1 概述
- 在进行项目开发的过程之中,所有重要的数据内容一般都需要通过日志的形式进行输出,既然 Gradle 是以 Groovy 语言编写的可编程的构建工具,那么在进行每一个任务处理的时候也可以进行日志的配置,同时在 Gradle 内部直接提供有各种日志的组件。
1.2 日志输出
- 所有的日志都是有日志等级的: | 等级 | 描述 | | —- | —- | | ERROR | 错误消息 | | QUIET | 重要消息信息 | | WARN | 警告信息 | | LIFECYCLE | 进度消息信息 | | INFO | 信息消息 | | DEBUG | 调试信息 |
- 使用不同的日志等级实现日志信息的打印,修改 build.gradle 文件:
task helloTask {
doFirst {
logger.log(LogLevel.ERROR,'【ERROR】这是一个 ERROR 级别日志信息')
logger.quiet('【QUIET】这是一个 QUIET 级别日志信息')
logger.info('【INFO】这是一个 INFO 级别日志信息')
logger.log(LogLevel.WARN,'【WARN】这是一个 WARN 级别日志信息')
logger.debug('【DEBUG】这是一个 DEBUG 级别日志信息')
logger.lifecycle('【LIFE_CYCLE】这是一个 LIFE_CYCLE 级别日志信息')
}
}
- 程序执行命令:
gradle helloTask
- 程序执行结果:
14:20:01: 正在执行 'helloTask'…
> Task :helloTask
【QUIET】这是一个 QUIET 级别日志信息
【WARN】这是一个 WARN 级别日志信息
【LIFE_CYCLE】这是一个 LIFE_CYCLE 级别日志信息
BUILD SUCCESSFUL in 58ms
1 actionable task: 1 executed
【ERROR】这是一个 ERROR 级别日志信息
14:20:02: 执行完成 'helloTask'。
- 这个时候日志的确是提供了,但是默认情况下执行的任务并不会触发所有的日志输出操作,如果要想获得指定类型的日志信息,那么就需要在任务执行的时候进行配置了。
1.3 日志控制
- 对于不同级别的日志,需要通过任务执行的时候配置不同的日志等级才可以实现输出,对于日志等级有如下的几个配置项: | 选项 | 输出日志级别 | | —- | —- | | 没有日志选项 | LIFECYCLE 或更高 | | -q 或 —quiet | QUIET 或更高 | | -w 或 —warn | WARN 或更高 | | -i 或 —info | INFO 或更高 | | -d 或 —debug | DEBUG 或更高 |
对于所有的日志,肯定要设置输出级别才能准确获取相应的日志信息。
示例:使用 debug 日志范围
- 程序执行命令:
gradle helloTask --debug
- 程序执行结果:
2021-12-27T14:26:58.616+0800 [QUIET] [org.gradle.api.Task] 【QUIET】这是一个 QUIET 级别日志信息
2021-12-27T14:26:58.616+0800 [INFO] [org.gradle.api.Task] 【INFO】这是一个 INFO 级别日志信息
2021-12-27T14:26:58.616+0800 [WARN] [org.gradle.api.Task] 【WARN】这是一个 WARN 级别日志信息
2021-12-27T14:26:58.616+0800 [DEBUG] [org.gradle.api.Task] 【DEBUG】这是一个 DEBUG 级别日志信息
2021-12-27T14:26:58.616+0800 [LIFECYCLE] [org.gradle.api.Task] 【LIFE_CYCLE】这是一个 LIFE_CYCLE 级别日志信息
第二章:Gradle 项目源代码打包
2.1 概述
- 对于任何一个项目来说,除了需要将核心的功能程序(编译后的)进行打包处理之外,实际上还需要考虑的就是开源项目中的源代码的打包操作,对于源代码的打包操作,需要单独配置有一个 Gradle 任务才可以实现。
2.2 源代码任务
- 如果要想进行源代码的打包,那么需要定义个新的任务,但是这个任务需要继承一个 jar 已有的任务,修改 build.gradle 文件:
// 最终生成的 jar 文件名称:baseName-version-classifier.extension
task sourceJar(type: Jar) { // 定义一个源代码的打包任务
archiveBaseName.set 'gradle-01' // 生成 jar 文件的名称
archiveVersion.set '1.0.0' // 定义项目打包版本
archiveClassifier.set 'sources' // 文件的分类
from sourceSets.main.allSource // 所有源代码的读取路径
exclude(['**/*.xml', '**/*.properties']) // 排除配置文件,可选
destinationDirectory.file("$buildDir/source-jar") // 目标存储路径
manifest {
attributes 'packageName': 'com.github.fairy.era',
'Built-By': '许大仙',
'Built-date': new Date().format('yyyy-MM-dd HH:mm:ss'),
'Manifest-Version': archiveVersion
}
}
- 完整的 build.gradle 文件:
plugins {
id 'java' // 配置的是一个 Java 插件(Java 项目)
id 'java-library'
}
ext {
jdkVersion = JavaVersion.VERSION_1_8 // 传统的 JDK 版本都是需要自己编写字符串的,而 Gradle 中提供了这样的操作
}
apply from: 'dependencies.gradle' // 引入所有的依赖文件
configurations { // 进行依赖的配置
implementation {
canBeConsumed = true
canBeResolved = true
}
}
group 'com.github.fairy.era' // 组织名称
version '1.0' // 项目版本
// 定义一个公共的变量描述当前使用的 JDK 版本
sourceCompatibility = jdkVersion
targetCompatibility = jdkVersion
repositories { // 仓库配置
mavenCentral()
}
dependencies { // 依赖管理
// compile gradleApi()
/* junit 5 */
testImplementation( // 如果有多个依赖,使用 , 隔开
libraries.'junit-jupiter'
)
/* druid */
implementation( // 如果有多个依赖,使用 , 隔开
libraries.'druid'
)
}
tasks.withType(JavaCompile) { // 针对程序编译的任务进行配置
options.encoding = "UTF-8"
}
def mainClassName = 'com.github.fairy.era.GradleMain' // 程序的主类名称
jar {
archivesBaseName = 'gradle' // 生成的 jar 文件名称,如果不写此名称则使用项目名称
manifestContentCharset = 'UTF-8' // 设置整个文件的编码
metadataCharset = 'UTF-8' // 元数据设置编码
manifest {
attributes 'Manifest-Version': getArchiveVersion().getOrNull(), // 程序版本号
'Main-Class': "${mainClassName}",// 程序主类名称
'Implementation-Title': 'hello-gradle',// 程序主类名称
'Implementation-Version': archiveVersion // 版本编号
}
into('lib') { // 将程序锁需要的第三方组件包配置到 lib 目录之中
from configurations.compileClasspath
}
}
test { // 进行测试任务的配置
useJUnitPlatform() // 使用 Junit 平台
}
sourceSets { // 建立源代码的目录集合
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources', 'src/main/config']
}
}
}
// 最终生成的 jar 文件名称:baseName-version-classifier.extension
task sourceJar(type: Jar) { // 定义一个源代码的打包任务
archiveBaseName.set 'gradle-01' // 生成 jar 文件的名称
archiveVersion.set '1.0.0' // 定义项目打包版本
archiveClassifier.set 'sources' // 文件的分类
from sourceSets.main.allSource // 所有源代码的读取路径
exclude(['**/*.xml', '**/*.properties']) // 排除配置文件,可选
destinationDirectory.file("$buildDir/source-jar") // 目标存储路径
manifest {
attributes 'packageName': 'com.github.fairy.era',
'Built-By': '许大仙',
'Built-date': new Date().format('yyyy-MM-dd HH:mm:ss'),
'Manifest-Version': archiveVersion
}
}
2.3 打包处理
- 既然此时已经明确的定义一个打包任务,那么就可以直接通过此任务的执行来实现源代码包的生成。
- 程序执行命令:
gradle sourceJar
- 程序执行结果:
2.4 打包时机
- 当前的操作虽然可以编写任务实现源代码的打包处理操作,但是有一个问题:通常是在程序最终编译的时候才进行打包处理,如果按照以上的方式单独定义一个新的任务,则意味着需要在整个程序之中单独配置任务,能够将这些任务合并在一起?
- 修改 build.gradle 文件:
task sourceJar(type: Jar,dependsOn: classes) { // 定义一个源代码的打包任务,并依赖于 classes 这种 Gradle 内置的任务
archiveClassifier.set 'sources' // 文件的分类
from sourceSets.main.allSource // 所有源代码的读取路径
}
2.5 命令整合
- 以上的任务仅仅是对已有的任务做了一个扩展,但是需要注意的是,毕竟现在的需求是将整个源代码的操作放在 build 之中,所以还需要进行一个额外的配置,修改 build.gradle 文件:
// 最终生成的 jar 文件名称:baseName-version-classifier.extension
task sourceJar(type: Jar,dependsOn: classes) { // 定义一个源代码的打包任务,并依赖于 classes 这种 Gradle 内置的任务
archiveClassifier.set 'sources' // 文件的分类
from sourceSets.main.allSource // 所有源代码的读取路径
}
artifacts { // 最终的打包操作任务
archives sourceJar
}
- 完整的 build.gradle 文件:
plugins {
id 'java' // 配置的是一个 Java 插件(Java 项目)
id 'java-library'
}
ext {
jdkVersion = JavaVersion.VERSION_1_8 // 传统的 JDK 版本都是需要自己编写字符串的,而 Gradle 中提供了这样的操作
}
apply from: 'dependencies.gradle' // 引入所有的依赖文件
configurations { // 进行依赖的配置
implementation {
canBeConsumed = true
canBeResolved = true
}
}
group 'com.github.fairy.era' // 组织名称
version '1.0' // 项目版本
// 定义一个公共的变量描述当前使用的 JDK 版本
sourceCompatibility = jdkVersion
targetCompatibility = jdkVersion
repositories { // 仓库配置
mavenCentral()
}
dependencies { // 依赖管理
// compile gradleApi()
/* junit 5 */
testImplementation( // 如果有多个依赖,使用 , 隔开
libraries.'junit-jupiter'
)
/* druid */
implementation( // 如果有多个依赖,使用 , 隔开
libraries.'druid'
)
}
tasks.withType(JavaCompile) { // 针对程序编译的任务进行配置
options.encoding = "UTF-8"
}
def mainClassName = 'com.github.fairy.era.GradleMain' // 程序的主类名称
jar {
archivesBaseName = 'gradle' // 生成的 jar 文件名称,如果不写此名称则使用项目名称
manifestContentCharset = 'UTF-8' // 设置整个文件的编码
metadataCharset = 'UTF-8' // 元数据设置编码
manifest {
attributes 'Manifest-Version': getArchiveVersion().getOrNull(), // 程序版本号
'Main-Class': "${mainClassName}",// 程序主类名称
'Implementation-Title': 'hello-gradle',// 程序主类名称
'Implementation-Version': archiveVersion // 版本编号
}
into('lib') { // 将程序锁需要的第三方组件包配置到 lib 目录之中
from configurations.compileClasspath
}
}
test { // 进行测试任务的配置
useJUnitPlatform() // 使用 Junit 平台
}
sourceSets { // 建立源代码的目录集合
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources', 'src/main/config']
}
}
}
// 最终生成的 jar 文件名称:baseName-version-classifier.extension
task sourceJar(type: Jar,dependsOn: classes) { // 定义一个源代码的打包任务,并依赖于 classes 这种 Gradle 内置的任务
archiveClassifier.set 'sources' // 文件的分类
from sourceSets.main.allSource // 所有源代码的读取路径
}
artifacts { // 最终的打包操作任务
archives sourceJar
}
- 程序执行命令:
gradle clean build -x test
- 程序执行结果:
第三章:Gradle 打包 javadoc
3.1 概述
- 一个完整的项目在进行打包的时候一个会有三个
*.jar
文件:主程序(gradle-1.0.jar)、源代码(gradle-1.0-sources.jar)和文档(gradle-1.0-javadoc.jar),如果要生成程序的 javadoc 文档,那么首先一定需要在项目中追加相应的文档说明,同时还需要在 build.gradle 文件中定义有相关的任务处理。
3.2 文档注释
- 略(一般项目中都需要写文档注释的)。
3.3 Gradle 的任务配置
- 如果要想生成 javadoc,则需要配置有相关的任务,Gradle 里面已经有了这样的内置任务,我们只需要对 javadoc 任务做一个继承处理即可,修改 build.gradle 文件:
task javaDocTask(type: Javadoc){
source sourceSets.main.allJava // 定义所有的 Java 源代码的路径
}
tasks.withType(Javadoc){ // 文档生成一定要有乱码处理
options.encoding = "UTF-8"
}
tasks.withType(JavaCompile) { // 针对程序编译的任务进行配置
options.encoding = "UTF-8"
}
- 程序执行命令:
gradle javaDocTask
- 程序执行结果:
- 当命令执行完成之后,会自动在 build/docs/javadoc 目录下生成所有的 JavaDoc 文档。
3.4 打包 JavaDoc
- 最终在进行项目发布的时候,肯定要生成 javadoc 的 jar 文件,此时就需要定义一个打包任务,修改 build.gradle 文件:
task javaDocJar(type: Jar, dependsOn: javaDocTask) { // 先生成 javadoc,才可以打包
archiveClassifier.set 'javadoc' // 文件的分类
from javaDocTask.destinationDir // 通过 javaDocTask 任务中找到目标路径
}
3.5 命令整合
- javadoc 的生成也应该在整个压缩结构文件生成的同时进行创建,修改 build.gradle 文件:
task javaDocTask(type: Javadoc) {
source sourceSets.main.allJava // 定义所有的 Java 源代码的路径
}
tasks.withType(Javadoc) { // 文档生成一定要有乱码处理
options.encoding = "UTF-8"
}
tasks.withType(JavaCompile) { // 针对程序编译的任务进行配置
options.encoding = "UTF-8"
}
task javaDocJar(type: Jar, dependsOn: javaDocTask) { // 先生成 javadoc,才可以打包
archiveClassifier.set 'javadoc' // 文件的分类
from javaDocTask.destinationDir // 通过 javaDocTask 任务中找到目标路径
}
artifacts { // 最终的打包操作任务
archives sourceJar
archives javaDocJar
}
- 完整的 build.gradle 文件:
plugins {
id 'java' // 配置的是一个 Java 插件(Java 项目)
id 'java-library'
}
ext {
jdkVersion = JavaVersion.VERSION_1_8 // 传统的 JDK 版本都是需要自己编写字符串的,而 Gradle 中提供了这样的操作
}
apply from: 'dependencies.gradle' // 引入所有的依赖文件
configurations { // 进行依赖的配置
implementation {
canBeConsumed = true
canBeResolved = true
}
}
group 'com.github.fairy.era' // 组织名称
version '1.0' // 项目版本
// 定义一个公共的变量描述当前使用的 JDK 版本
sourceCompatibility = jdkVersion
targetCompatibility = jdkVersion
repositories { // 仓库配置
mavenCentral()
}
dependencies { // 依赖管理
// compile gradleApi()
/* junit 5 */
testImplementation( // 如果有多个依赖,使用 , 隔开
libraries.'junit-jupiter'
)
/* druid */
implementation( // 如果有多个依赖,使用 , 隔开
libraries.'druid'
)
}
def mainClassName = 'com.github.fairy.era.GradleMain' // 程序的主类名称
jar {
archivesBaseName = 'gradle' // 生成的 jar 文件名称,如果不写此名称则使用项目名称
manifestContentCharset = 'UTF-8' // 设置整个文件的编码
metadataCharset = 'UTF-8' // 元数据设置编码
manifest {
attributes 'Manifest-Version': getArchiveVersion().getOrNull(), // 程序版本号
'Main-Class': "${mainClassName}",// 程序主类名称
'Implementation-Title': 'hello-gradle',// 程序主类名称
'Implementation-Version': archiveVersion // 版本编号
}
into('lib') { // 将程序锁需要的第三方组件包配置到 lib 目录之中
from configurations.compileClasspath
}
}
test { // 进行测试任务的配置
useJUnitPlatform() // 使用 Junit 平台
}
sourceSets { // 建立源代码的目录集合
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources', 'src/main/config']
}
}
}
// 最终生成的 jar 文件名称:baseName-version-classifier.extension
task sourceJar(type: Jar, dependsOn: classes) { // 定义一个源代码的打包任务,并依赖于 classes 这种 Gradle 内置的任务
archiveClassifier.set 'sources' // 文件的分类
from sourceSets.main.allSource // 所有源代码的读取路径
}
task javaDocTask(type: Javadoc) {
source sourceSets.main.allJava // 定义所有的 Java 源代码的路径
}
tasks.withType(Javadoc) { // 文档生成一定要有乱码处理
options.encoding = "UTF-8"
}
tasks.withType(JavaCompile) { // 针对程序编译的任务进行配置
options.encoding = "UTF-8"
}
task javaDocJar(type: Jar, dependsOn: javaDocTask) { // 先生成 javadoc,才可以打包
archiveClassifier.set 'javadoc' // 文件的分类
from javaDocTask.destinationDir // 通过 javaDocTask 任务中找到目标路径
}
artifacts { // 最终的打包操作任务
archives sourceJar
archives javaDocJar
}
- 程序执行命令:
gradle clean build -x test
- 程序执行结果:
第四章:Gradle 程序测试控制
4.1 概述
- 在 Gradle 项目中所有的代码都要有相应的测试用例存在,但是如果说在一些环境下测试用例可能无法正常执行,那么面对这样的情况,就需要每次在编译打包的时候都使用
-x test
来跳过测试。 - 在 Maven 里面有一种插件,通过配置可以避免执行测试的代码,但是在 Gradle 中并没有这样的插件,如果要想实现测试代码的跳过,就需要手工编写程序。
4.2 错误测试
- 为了更好的说明问题,首先编写一个错误的测试代码:
package com.github.era.fairy.service;
import com.github.fairy.era.service.IMessageService;
import com.github.fairy.era.service.impl.MessageServiceImpl;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/**
* @author 许大仙
* @version 1.0
* @since 2021-12-21 08:43
*/
public class MessageServiceTest {
@Test
public void test() {
IMessageService messageService = new MessageServiceImpl();
Assertions.assertEquals("你好啊", messageService.echo("Gradle"));
}
}
- 程序执行结果:
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :compileTestJava
> Task :processTestResources NO-SOURCE
> Task :testClasses
> Task :test FAILED
expected: <你好啊> but was: <hello Gradle>
预期:你好啊
实际:hello Gradle
<点击以查看差异>
org.opentest4j.AssertionFailedError: expected: <你好啊> but was: <hello Gradle>
at com.github.era.fairy.service.MessageServiceTest.test(MessageServiceTest.java:18)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at java.util.ArrayList.forEach(ArrayList.java:1249)
MessageServiceTest > test() FAILED
org.opentest4j.AssertionFailedError at MessageServiceTest.java:18
1 test completed, 1 failed
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at: file:///D:/project/gradle-01/build/reports/tests/test/index.html
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 1s
4 actionable tasks: 2 executed, 2 up-to-date
4.3 代码影响
- 这样的程序代码在进行编译打包时候,一定会带来无法正常运行的问题。
- 程序执行命令:
gradle clean build
- 程序执行结果:
Execution failed for task ':test'.
> There were failing tests. See the report at: file:///D:/project/gradle-01/build/reports/tests/test/index.html
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
- 传统的解决方式就是使用
-x test
命令参数来进行控制,但是太麻烦了。
4.4 测试的控制任务
- 如果要想解决当前测试代码对整个程序的影响,可以考虑做一个开关,修改 build.gradle 文件:
gradle.taskGraph.whenReady { // 在所有的操作准备好之后触发
tasks.each { task ->
if (task.name.contains('test')) { // 如果发现有 test 任务,就跳过
task.enabled = false // 当前任务不执行
}
}
}
- 当项目中配置了这样的处理之后,实际上最终所有的程序的测试都会失效,因为只要发现是测试的指令,就会关闭任务处理。
第五章:Gradle 多环境配置管理
5.1 概述
- 一个项目如果要想正常使用,则一般会经历:开发环境、测试环境和线上环境,不同的环境对于一些程序的配置信息也有所不同,那么这样的操作都可以通过 profile 来进行配置。
- 按照正常的开发逻辑,应该将所有的网络服务器的信息,保存在不同的 profile 文件里面,例如:现在假设在 src/main 目录下创建一个 profiles 公共目录。
.
|-- LICENSE
|-- build.gradle
|-- gradle
| `-- wrapper
| |-- gradle-wrapper.jar
| `-- gradle-wrapper.properties
|-- gradlew
|-- gradlew.bat
|-- settings.gradle
`-- src
|-- main
| |-- config
| | |-- database.properties
| | |-- dubbo.properties
| | `-- redis.properties
| |-- java
| |-- profiles # 公共目录
| | |-- dev # 开发环境
| | | `-- config
| | | `-- database.properties
| | |-- prod # 生产环境
| | | `-- config
| | | `-- database.properties
| | `-- test # 测试环境
| | `-- config
| | `-- database.properties
| `-- resources
`-- test
|-- java
`-- resources
5.2 定义 profile
- 以上的三个不同的属性文件在项目中的所有 key 的内容是相同的,不同的仅仅是 key 对应的 value ,在程序执行的时候就可以根据不同的环境实现配置的切换。
- src/main/profiles/dev/config/database.properties:
druid.database.name=gradle-dev
druid.database.username=gradle-dev
- src/main/profiles/test/config/database.properties:
druid.database.name=gradle-prod
druid.database.username=gradle-prod
- src/main/profiles/prod/config/database.properties:
druid.database.name=gradle-test
druid.database.username=gradle-test
5.3 Gradle 配置
- 如果要想让当前的这个 profile 路径生效,则一定要修改 build.gradle 配置文件,在这个配置文件里面定义源代码的访问路径,但是这个路径需要注意的是,里面的 profile 名称是需要动态变更的。
| 环境 | profile 路径 |
| —- | —- |
| 开发环境 | src/main/profiles/
dev
/config/database.properties | | 测试环境 | src/main/profiles/test
/config/database.properties | | 生产环境 | src/main/profiles/prod
/config/database.properties |
- 修改 build.gradle 文件,获取 env 环境属性:
def env = System.getProperty("env")?:'dev' // 获取 env 的环境属性
- 对于当前可以接受的 env 环境属性,实际上就属于最终的
src/main/profiles/xxx
的动态内容,最终所需要的 profile 的具体内容就是由这个变量决定的,那么修改 build.gradle 文件:
sourceSets { // 建立源代码的目录集合
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources', 'src/main/config', "src/main/profiles/${env}"]
}
}
}
- 完整的 build.gradle 文件:
plugins {
id 'java' // 配置的是一个 Java 插件(Java 项目)
id 'java-library'
}
ext {
jdkVersion = JavaVersion.VERSION_1_8 // 传统的 JDK 版本都是需要自己编写字符串的,而 Gradle 中提供了这样的操作
}
apply from: 'dependencies.gradle' // 引入所有的依赖文件
configurations { // 进行依赖的配置
implementation {
canBeConsumed = true
canBeResolved = true
}
}
group 'com.github.fairy.era' // 组织名称
version '1.0' // 项目版本
// 定义一个公共的变量描述当前使用的 JDK 版本
sourceCompatibility = jdkVersion
targetCompatibility = jdkVersion
def env = System.getProperty("env")?:'dev' // 获取 env 的环境属性
repositories { // 仓库配置
mavenCentral()
}
dependencies { // 依赖管理
// compile gradleApi()
/* junit 5 */
testImplementation( // 如果有多个依赖,使用 , 隔开
libraries.'junit-jupiter'
)
/* druid */
implementation( // 如果有多个依赖,使用 , 隔开
libraries.'druid'
)
}
def mainClassName = 'com.github.fairy.era.GradleMain' // 程序的主类名称
jar {
archivesBaseName = 'gradle' // 生成的 jar 文件名称,如果不写此名称则使用项目名称
manifestContentCharset = 'UTF-8' // 设置整个文件的编码
metadataCharset = 'UTF-8' // 元数据设置编码
manifest {
attributes 'Manifest-Version': getArchiveVersion().getOrNull(), // 程序版本号
'Main-Class': "${mainClassName}",// 程序主类名称
'Implementation-Title': 'hello-gradle',// 程序主类名称
'Implementation-Version': archiveVersion // 版本编号
}
into('lib') { // 将程序锁需要的第三方组件包配置到 lib 目录之中
from configurations.compileClasspath
}
}
test { // 进行测试任务的配置
useJUnitPlatform() // 使用 Junit 平台
}
sourceSets { // 建立源代码的目录集合
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources', 'src/main/config', "src/main/profiles/${env}"]
}
}
}
gradle.taskGraph.whenReady { // 在所有的操作准备好之后触发
tasks.each { task ->
if (task.name.contains('test')) { // 如果发现有 test 任务,就跳过
task.enabled = true // 当前任务不执行
}
}
}
// 最终生成的 jar 文件名称:baseName-version-classifier.extension
task sourceJar(type: Jar, dependsOn: classes) { // 定义一个源代码的打包任务,并依赖于 classes 这种 Gradle 内置的任务
archiveClassifier.set 'sources' // 文件的分类
from sourceSets.main.allSource // 所有源代码的读取路径
}
task javaDocTask(type: Javadoc) {
source sourceSets.main.allJava // 定义所有的 Java 源代码的路径
}
tasks.withType(Javadoc) { // 文档生成一定要有乱码处理
options.encoding = "UTF-8"
}
tasks.withType(JavaCompile) { // 针对程序编译的任务进行配置
options.encoding = "UTF-8"
}
task javaDocJar(type: Jar, dependsOn: javaDocTask) { // 先生成 javadoc,才可以打包
archiveClassifier.set 'javadoc' // 文件的分类
from javaDocTask.destinationDir // 通过 javaDocTask 任务中找到目标路径
}
artifacts { // 最终的打包操作任务
archives sourceJar
archives javaDocJar
}
5.4 打包处理
- 此时给出的是一个 Java 环境属性,所以环境属性可以采用
-D属性名称 = 内容
的形式来进行处理,而后要进行程序的打包配置。 - 开发环境打包命令(任选其一即可):
gradle clean build
gradle clean build -Denv=dev
- 测试环境打包命令:
gradle clean build -Denv=test
- 生产环境打包命令:
gradle clean build -Denv=prod
5.5 依赖配置
- 长期以来如果使用 Maven 都会发现有一个核心问题:依赖库的版本永远都是需要固定配置,即使有不同的 profile,依赖库也是无法变更的;但是在 Gradle 里面,将这个问题解决了,在之前为了进行依赖的统一管理,提供有一个 dependencies.gradle 的配置文件,那么如果要想实现不同版本的切换,就可以通过这样的文件形式来进行控制。
- 下面建立
dependencies-xxx.gradle
的配置文件,其中xxx
代表 dev、test 和 prod。 - dependencies-dev.gradle 的内容如下:
// 定义所有要使用的版本号
ext.versions = [
junitJupiterVersion: '5.8.0',
druidVersion : '1.2.6'
]
// 定义所有的依赖库
ext.libraries = [
/* junit 5 */
'junit-jupiter': "org.junit.jupiter:junit-jupiter:${versions.junitJupiterVersion}",
/* druid */
druid : "com.alibaba:druid:${versions.druidVersion}"
]
- dependencies-test .gradle 的内容如下:
// 定义所有要使用的版本号
ext.versions = [
junitJupiterVersion: '5.8.1',
druidVersion : '1.2.7'
]
// 定义所有的依赖库
ext.libraries = [
/* junit 5 */
'junit-jupiter': "org.junit.jupiter:junit-jupiter:${versions.junitJupiterVersion}",
/* druid */
druid : "com.alibaba:druid:${versions.druidVersion}"
]
- dependencies-prod.gradle 的内容如下:
// 定义所有要使用的版本号
ext.versions = [
junitJupiterVersion: '5.8.2',
druidVersion : '1.2.8'
]
// 定义所有的依赖库
ext.libraries = [
/* junit 5 */
'junit-jupiter': "org.junit.jupiter:junit-jupiter:${versions.junitJupiterVersion}",
/* druid */
druid : "com.alibaba:druid:${versions.druidVersion}"
]
5.6 动态导入
- 修改 build.gradle 文件,针对于依赖配置库进行动态配置:
def env = System.getProperty("env")?:'dev' // 获取 env 的环境属性
apply from: "dependencies-${env}.gradle" // 引入所有的依赖文件
- 开发环境打包命令:
gradle clean build
gradle clean build -Denv=dev
- 测试环境打包命令:
gradle clean build -Denv=test
- 生产环境打包命令:
gradle clean build -Denv=prod
- 完成的 build.gradle 文件:
plugins {
id 'java' // 配置的是一个 Java 插件(Java 项目)
id 'java-library'
}
ext {
jdkVersion = JavaVersion.VERSION_1_8 // 传统的 JDK 版本都是需要自己编写字符串的,而 Gradle 中提供了这样的操作
}
def env = System.getProperty("env")?:'dev' // 获取 env 的环境属性
apply from: "dependencies-${env}.gradle" // 引入所有的依赖文件
configurations { // 进行依赖的配置
implementation {
canBeConsumed = true
canBeResolved = true
}
}
group 'com.github.fairy.era' // 组织名称
version '1.0' // 项目版本
// 定义一个公共的变量描述当前使用的 JDK 版本
sourceCompatibility = jdkVersion
targetCompatibility = jdkVersion
repositories { // 仓库配置
mavenCentral()
}
dependencies { // 依赖管理
// compile gradleApi()
/* junit 5 */
testImplementation( // 如果有多个依赖,使用 , 隔开
libraries.'junit-jupiter'
)
/* druid */
implementation( // 如果有多个依赖,使用 , 隔开
libraries.'druid'
)
}
def mainClassName = 'com.github.fairy.era.GradleMain' // 程序的主类名称
jar {
archivesBaseName = 'gradle' // 生成的 jar 文件名称,如果不写此名称则使用项目名称
manifestContentCharset = 'UTF-8' // 设置整个文件的编码
metadataCharset = 'UTF-8' // 元数据设置编码
manifest {
attributes 'Manifest-Version': getArchiveVersion().getOrNull(), // 程序版本号
'Main-Class': "${mainClassName}",// 程序主类名称
'Implementation-Title': 'hello-gradle',// 程序主类名称
'Implementation-Version': archiveVersion // 版本编号
}
into('lib') { // 将程序锁需要的第三方组件包配置到 lib 目录之中
from configurations.compileClasspath
}
}
test { // 进行测试任务的配置
useJUnitPlatform() // 使用 Junit 平台
}
sourceSets { // 建立源代码的目录集合
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources', 'src/main/config', "src/main/profiles/${env}"]
}
}
}
gradle.taskGraph.whenReady { // 在所有的操作准备好之后触发
tasks.each { task ->
if (task.name.contains('test')) { // 如果发现有 test 任务,就跳过
task.enabled = true // 当前任务不执行
}
}
}
// 最终生成的 jar 文件名称:baseName-version-classifier.extension
task sourceJar(type: Jar, dependsOn: classes) { // 定义一个源代码的打包任务,并依赖于 classes 这种 Gradle 内置的任务
archiveClassifier.set 'sources' // 文件的分类
from sourceSets.main.allSource // 所有源代码的读取路径
}
task javaDocTask(type: Javadoc) {
source sourceSets.main.allJava // 定义所有的 Java 源代码的路径
}
tasks.withType(Javadoc) { // 文档生成一定要有乱码处理
options.encoding = "UTF-8"
}
tasks.withType(JavaCompile) { // 针对程序编译的任务进行配置
options.encoding = "UTF-8"
}
task javaDocJar(type: Jar, dependsOn: javaDocTask) { // 先生成 javadoc,才可以打包
archiveClassifier.set 'javadoc' // 文件的分类
from javaDocTask.destinationDir // 通过 javaDocTask 任务中找到目标路径
}
artifacts { // 最终的打包操作任务
archives sourceJar
archives javaDocJar
}