项目结构
IDEA创建一个Gradle项目
Gradle项目结构
project
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── subproject-a
│ ├── build.gradle
│ └── src
└── subproject-b
├── build.gradle
└── src
当我们创建一个新的Gradle项目时,其项目目录结构如上;
/gradle/wrapper/*
这个目录下就是当前项目的Gradle的包装,本质就是指向一个完整的指定版本的Gradle,所有的命令执行都可以基于这个包装去执行,执行的时候只需要根据相对路径使用到/.gradlew
(Mac & Linux) or ./gradlew.bat
(win)命令。(wrapper里面是没有gradle具体版本的bin文件,这些文件都存放在 GRADLE_USER_HOME/wrapper/dists
下,GRADLE_USER_HOME
可以自己去环境变量配置,默认是:Mac: ~/.gradle,win:C:\Users<USERNAME>.gradle)
我们还有一种使用Gradle命令的方法,就是下载一个Gradle,并且将该gradle的命令注册到环境变量中,那么整台电脑都有一个全局的gradle命令。但是并不建议这样使用,因为考虑到不同的项目有可能用的Gradle版本不同,同时也方便其他人开发项目的时候不会出现gradle版本不同的问题。
Gradle与项目代码之间的关系
上图就是官方手册给出的Gradle与开发项目、外部插件、外部依赖的关系模型,蓝色框住的就表示的是Wrapper包装的Gradle。
构建的三个阶段
当我们执行build的时候,gradle是按照下面三个阶段来将源代码里的配置和gradle的配置,转换成一个一个的Task。过程大致如下:
- 初始化 (Initialization)
- 检测
settings.gradle
文件。(下面详细说明settings.gradle文件) - 创建一个
Settings
实例。 - 评估设置文件以确定哪些项目(和包含的构建)组成构建。
Project
为每个项目创建一个实例。
- 配置 (Configuration)
build.gradle
评估参与构建的每个项目的构建脚本。- 为请求的任务创建任务图(有向无环)。
- 执行 (Execution)
- 安排并执行选定的任务。
- 任务之间的依赖关系决定了执行顺序。
- 任务的执行可以并行进行。
settings.gradle
在 Gradle Build 生命周期的早期,初始化阶段会在项目根目录中找到设置文件,并且实例化一个Settings
对象,所以说settings.gradle文件定义了一个Settings
对象。
Settings
对象是Gradle API里的一部分,Groovy DSL文档 & Kotlin DSL文档
Settings对象常用属性
姓名 | 描述 |
---|---|
buildCache | 构建缓存配置。 |
plugins | 已应用于设置的插件的容器。 |
rootDir | 构建的根目录。根目录是根项目的项目目录。 |
rootProject | 构建的根项目。 |
settings | 返回此设置对象。 |
属性设置的写法,例如设置根目录:
rootProject.name = 'gradle-demo'
常用方法:
姓名 | 描述 |
---|---|
include() | 将给定的项目添加到构建中。 |
includeBuild() | 将指定路径处的构建包含到复合构建中。 |
方法的调用,例如将子项目添加到构建:
include('subproject-a')
# 或者
include 'subproject-a'
下面给出一个完整的例子:
pluginManagement {
repositories {
gradlePluginPortal()
google()
}
}
// 这里的plugins跟build.gradle里的plugins作用不一样
// 这里会配置应用于整个项目的插件,比如构建脚本的配置或者对项目结构的修改
plugins {
id 'org.gradle.toolchains.fake' version '0.6.0'
}
rootProject.name = 'root-project'
dependencyResolutionManagement {
repositories {
mavenCentral()
}
}
include('sub-project-a')
include('sub-project-b')
include('sub-project-c')
build.gradle
在初始化阶段,会根据settings文件里配置的include的子项目和根项目,创建出Project
对象,而每个Project
对象都有一个build.gradle构建脚本。创建Project
对象时的配置用的就是这个构建脚本。
Project
对象是Gradle API里的一部分,Groovy DSL文档 & Kotlin DSL文档
下表列出了几个常用的属性:
姓名 | 类型 | 描述 |
---|---|---|
name | String | 项目目录的名称。 |
path | String | 项目的完全限定名称。 |
description | String | 项目的描述。 |
dependencies | DependencyHandler | 返回项目的依赖处理程序。 |
repositories | RepositoryHandler | 返回项目的存储库处理程序。 |
layout | ProjectLayout | 提供对项目几个重要位置的访问。 |
group | Object | 本项目的小组。 |
version | Object | 该项目的版本。 |
下表列出了几种常用的方法:
姓名 | 描述 |
---|---|
uri() | 将文件路径解析为相对于该项目的项目目录的 URI。 |
task() | 创建具有给定名称的任务并将其添加到该项目。 |
引入插件
plugins {
id 'java'
id 'application'
}
这里的plugins跟settings的作用不同,这里更多是针对具体的子项目(modules)或任务(tasks)进行配置。插件里更多是对构建行为中作出其他动作的任务。
设置仓库
repositories {
mavenLocal() // 本地仓库,主要是自己写的包发布时发布在本地时有用
mavenCentral() // maven中心仓库
maven {
url = "http://xxx/xxx"
allowInsecureProtocol = true
credentials {
username = "xxx"
password = "XXXXX"
} // 自己搭建的maven仓库
}
}
用于配置源代码所需要的依赖的仓库位置。
引入依赖
dependencies {
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit5'
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.3'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'com.google.guava:guava:32.1.1-jre'
// **依赖的写法:**
// **完整的依赖简写**
implementation 'com.auth0:java-jwt:4.0.0'
// **完整的依赖全称**
implementation group: 'com.googlecode.libphonenumber', name: 'libphonenumber', version: '8.12.47'
// 排除掉依赖里的某个依赖
implementation('io.reflectoring:sqs-starter:0.0.11') {
exclude group: 'com.fasterxml.jackson.core'
}
// --------------------------------------------------------------------------
// **引入依赖的五种方式**
// 1. **通过Maven中央仓库引入依赖:**
implementation 'group:artifact:version'
// 2. **通过本地文件引入依赖:**
implementation files('libs/some-library.jar')
// 3. **通过项目的子模块引入依赖:**
implementation project(':submodule')
// 4. **通过远程仓库引入依赖(例如GitHub):**
implementation 'com.github.username:repository:version'
// 5. **通过URL引入依赖:**
implementation 'group:artifact:version@jarUrl'
}
这个就是给源代码添加依赖包,其中引入的方法有很多种:
名称 | 描述 |
---|---|
compileOnly | 由java插件提供,适用于编译器需要单打包不需要的情况 |
runtimeOnly | 由java插件提供,只在运行时需要,编译时不需要 |
implementation | 由java插件提供,针对src/main目录,在编译运行时都有效 |
testCompileOnly | 由java插件提供,用于编译测试依赖项,运行时不需要 |
testRuntimeOnly | 由java插件提供,只在测试运行时有用 |
testImplementation | 由java插件提供,仅用于测试使用 |
api | 由java-library插件提供,与implementation作用相似,不过api支持依赖传递 |
compileOnlyApi | 由java-library插件提供,仅在编译时有用,支持依赖传递 |
依赖传递就是指:一个项目a引入了一个依赖包b,这个依赖包b里用的依赖c如果是api引入的,那么项目里也可以引入这个依赖c,如果依赖c是用implementation引入依赖b,那么项目a就不会引入这个依赖c。api在多项目的情况可以减少很多重复依赖,但也容易导致依赖冲突。
依赖冲突的解决方案:
- Gradle默认处理方法:选高版本
- 手动排除有依赖的依赖包
- 不允许依赖传递,即将
exclude group: 'com.fasterxml.jackson.core'
换成transitive(false)
(不建议使用) - 强制使用某个版本:
implementation 'com.auth0:java-jwt:4.0.0**!!**'
后面两个感叹号就是强制使用的意思
注册并配置任务
tasks.named('test') {
useJUnitPlatform()
}
自定义Task
- 创建任务类
在项目的源代码目录中创建一个新的类,该类将会实现你的自定义任务逻辑。通常情况下,自定义任务继承自 Gradle 的 DefaultTask
类或者其它合适的任务类型。
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
class MyCustomTask extends DefaultTask {
@TaskAction
void myTaskAction() {
// 在这里编写你的任务逻辑
println '执行自定义任务...'
}
}
- 注册任务
在项目的构建脚本中注册你的自定义任务。如果你的项目是单模块的,那么你可以在 build.gradle
中注册任务;如果是多模块项目,你可以在根项目的 settings.gradle
或者子项目的 build.gradle
中注册任务。
// build.gradle
task myCustomTask(type: MyCustomTask) {
// 在这里可以配置任务的属性
}
2-1. 配置任务
你可以在任务注册时对其进行配置,比如设置任务的输入、输出、依赖关系等等。
task myCustomTask(type: MyCustomTask) {
// 配置任务的输入
inputs.property('someInput', 'inputValue')
// 配置任务的输出
outputs.dir('build/outputDirectory')
// 配置任务的依赖关系
dependsOn 'someOtherTask'
}
- 运行任务
在命令行中使用 Gradle 执行你的自定义任务。
./gradlew myCustomTask