环境描述
描述项 | 内容 |
---|---|
操作系统 | CentOS Linux release 7.8.2003 (Core) |
java版本 | java version "1.8.0_161" |
IDEA版本 | 2022.2.2 |
Gradle版本 | 7.5 |
Gradle 默认内建了一个 init 插件,可以生成 Java 项目基础结构
具体命令如下:
$] gradle init --type <name>
其中的 name 可以是以下值
- java-application
- java-library
- scala-library
- groovy-library
- basic
这里选择java-application类型,具体步骤如下:
1. 创建目录
mkdir javaDemo
cd javaDemo
2. 初始化项目
gradle init --type java-application
这里直接回车,全部使用默认配置
2.1. gradle init 执行成功之后的目录结构如下
.
├── app
│ ├── build.gradle
│ └── src
│ ├── main # 源代码目录
│ │ ├── java
│ │ │ └── javademo
│ │ │ └── App.java
│ │ └── resources
│ └── test # 测试代码目录
│ ├── java
│ │ └── javademo
│ │ └── AppTest.java
│ └── resources
├── gradle #wrapper的文件
│ └── wrapper
│ ├── gradle-wrapper.jar # 具体业务逻辑
│ └── gradle-wrapper.properties # 配置文件
├── gradlew # gradlew是一个shell 脚本,Unix 用户可以通过它来执行 Gradle 任务。
├── gradlew.bat # gradlew.bat是bat 脚本,Windows 用户可以通过它执行 Gradle 任务,配合gradle文件夹使用。
└── settings.gradle
12 directories, 8 files
2.2 settings.gradle文件
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
*
* Detailed information about configuring a multi-project build in Gradle can be found
* in the user manual at https://docs.gradle.org/7.5/userguide/multi_project_builds.html
*/
rootProject.name = 'javaDemo'
include('app')
rootProject.name就是指定项目名称的,gradlew build生成的 jar 包就是[项目名称].jar。
另外 setting.gradle 用来告诉 gradle 这个项目还包含了那些子项目。
2.3. app/build.gradle 文件
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java application project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at https://docs.gradle.org/7.5/userguide/building_java_projects.html
*/
plugins {
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
}
/**
* 指定仓库的路径
* mavenCentral():表示使用中央仓库,即项目中的jar会从中央仓库下载到本地指定目录中
* C:/Users/Administrator/.gradle(可以在setting中的gradle中的service directory path进行自定义配置)
*/
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
/**
* gradle工程所有的jar包的坐标都在dependencies属性内放置
* 每一个jar包的坐标 都有3个基本元素:
* group,name,version
* 类似于maven中的 <groupId>,<artifactId>,<version>
* testImplementation:表示该jar包在测试的时候起作用,该属性为jar包的作用域
* 所以我们在添加jar包坐标的时候,都要带上jar包的作用域
*/
dependencies {
// Use JUnit Jupiter for testing. junit测试包
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
// This dependency is used by the application. google的guava包
implementation 'com.google.guava:guava:31.0.1-jre'
}
application {
// Define the main class for the application. main类
mainClass = 'javademo.App'
}
tasks.named('test') {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}
build文件中加了java和application两个插件。前者支持java项目,后者允许指定包含main方法的类,在run时执行。
2.4. app/src/main/java/javademo/App.java 代码
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package javademo;
public class App {
public String getGreeting() {
return "Hello World!";
}
public static void main(String[] args) { # 在运行application插件的run task 时调用
System.out.println(new App().getGreeting());
}
}
2.5. app/src/test/java/javademo/AppTest.java
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package javademo;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class AppTest {
@Test void appHasAGreeting() {
App classUnderTest = new App();
assertNotNull(classUnderTest.getGreeting(), "app should have a greeting");
}
}
2.6. gradle/wrapper/gradle-wrapper.properties
# 解压gradle的总目录
distributionBase=GRADLE_USER_HOME
# 解压gradle总目录下的目录
distributionPath=wrapper/dists
#下载gradle的地址,和版本
# 1. gradle-xx-all.zip是完整版,包含了各种二进制文件,源代码文件,和离线的文档。
# 2. gradle-xx-bin.zip是二进制版,只包含了二进制文件(可执行文件),没有文档和源代码。
# 3. gradle-xx-src.zip是源码版,只包含了Gradle源代码,不能用来编译你的工程。
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
# 下载gradle的总目录
zipStoreBase=GRADLE_USER_HOME
# 下载gradle总目录下的目录
zipStorePath=wrapper/dists
gradle-wrapper.properties文件主要指定了该项目需要什么版本的Gradle,从哪里下载该版本的Gradle,下载下来放到哪里。从图示项目中可以知道我要使用gradle-7.5版本。
我们使用gradlew命令的使用,会根据这个文件来使用对应的gradle进行构建。当本地GRADLE_USER_HOME
(当前用户目录,一般指 ~/.gradle
)中的 ~/.gradle/wrapper/dists
没有安装gradle时,将会自动从此地址distributionUrl中下载gradle,之后的执行将不会再次下载安装。
GRADLE_USER_HOME:环境变量(类似于JAVA_HOME),gradle的用户目录,里面放gradle的相关配置等,类似于maven的.m2的文件路径。
- Mac的默认目录是:/Users/xxx/.gradle
- Windows的默认目录是:C:/用户/xxx/.gradle
使用该文件的步骤如下:
- 解析gradle-wrapper.properties文件,获取项目需要的 gradle 版本下载地址。
- 判断本地用户目录下的
~/.gradle
目录下是否存在该版本,不存在该版本,走第3点,存在走第4点。 - 下载gradle-wrapper.properties指定版本,并解压到用户目录的下
~/.gradle
文件下。 - 利用
~/.gradle
目录下对应的版本的 gradle 进行相应自动编译操作。
3. 编译项目
现在有 2 种方式来编译这个示例项目,分别是
- 通过本机安装好的 gradle 命令编译
- 通过当前项目根目录下的 gradlew 命令编译(官方推荐的使用方式)
这里使用方式2
进行编译:
$ ./gradlew build
:compileJava
// Download of Guava if not already cached...
:processResources UP-TO-DATE
:classes
:jar
:startScripts
:distTar
:distZip
:assemble
:compileTestJava
// Download of JUnit if not already cached...
:processTestResources UP-TO-DATE
:testClasses
:test
:check
:build
BUILD SUCCESSFUL
第一次运行构建时,Gradle会检查您的缓存中是否已经有Guava和JUnit库 ~/.gradle
。如果没有,库将被下载并存储在那里。下次运行构建时,将使用缓存的版本。该build任务编译的类,运行测试,并生成测试报告。
您可以通过打开位于的HTML输出文件来查看测试报告 app/build/reports/tests/test/index.html
。
4. 运行项目
因为Gradle构建使用了Application plugin,所以可以从命令行运行应用程序。首先,使用tasks任务来看看插件添加了哪些任务。
$ ./gradlew tasks
:tasks
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
Application tasks
-----------------
run - Runs this project as a JVM application
// ... many other tasks ...
run task会让gradle读取mainClassName属性指定的类,执行main方法
$ ./gradlew run
:compileJava UP-TO-DATE
:processResources NO-SOURCE
:classes UP-TO-DATE
:run
Hello world.
BUILD SUCCESSFUL
附录
A. 相关联的文章
B. gradle proxy 代理配置
参考: https://blog.csdn.net/dalich/article/details/125166316
在gradle工程中,最好在以下两个文件中,均添加以上配置:
- ./gradle.properties
- ./gradle/wrapper/gradle-wrapper.properties
主要格式如下:
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=1080
systemProp.https.proxyHost=127.0.0.1
systemProp.https.proxyPort=1080
C. 仓库地址换成阿里
-
build.gradle(Groovy语法)
repositories { maven { url 'https://maven.aliyun.com/repository/jcenter' } maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/central' } maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } }
-
build.gradle.kts(Kotlin语法)
repositories { maven { setUrl( "https://maven.aliyun.com/repository/jcenter") } maven { setUrl( "https://maven.aliyun.com/repository/google") } maven { setUrl( "https://maven.aliyun.com/repository/central") } maven { setUrl( "https://maven.aliyun.com/repository/gradle-plugin") } }
-
Kotlin语法也可以简写
repositories { maven ("https://maven.aliyun.com/repository/jcenter") maven ( "https://maven.aliyun.com/repository/google") maven ( "https://maven.aliyun.com/repository/central") maven ( "https://maven.aliyun.com/repository/gradle-plugin") }
D. Gradle 基本原理
我们知道 Gradle 是一种以 Groovy 语言为基础的自动化构建工具,一般通过修改 build.gradle 脚本来完成对项目构建的一些设置,例如依赖管理等等。大多数情况下,我们只需要稍微修改下 gradle 文件即可完成自己的需求。
自动化构建工具听起来似乎比较复杂,本质上来说也是一种程序,跟我们自己写的代码一样,我们开始编译时就启动这个程序,然后读取我们在 gradle 文件中配置的参数来实例化各个类,然后按照顺序依次执行对应的任务即可完成整个构建任务。
所以 build.gradle 文件,或者其他后缀为 gradle 的文件其实就是个配置文件,就好像 xml 一样,我们在 gradle 文件中修改各种配置参数,Gradle 通过这些参数来实例化 Project 等等就像构造器一样,只要理解了这点学习 Gradle 就会变得很容易。
当我们新建一个项目后,Gradle 默认会生成一些编译脚本文件,主要有:setting.gradle、build.gradle 以及子项目中的 build.gradle 等等,还会在当前目录下生成一个 gradle 文件夹,下面分别介绍一些这些文件的作用:
-
setting.gradle 用来告诉 gradle 这个项目包含了那些子项目。
-
build.gradle 是默认的构建脚本,当我们在执行 gradle 命令时,会首先到当前目录下寻找该文件,然后通过该文件的配置实例化一个 Project 对象。
-
自动生成的 gradle 文件夹是 Gradle 包装器,其中包含一个 jar 文件和一个 配置文件,使用这个包装器可以让 Gradle 运行在一个特定的版本上,目的是创造一个独立于系统、系统配置和 Gradle 版本的可靠和可重复构建。
Gradle 中有两个重要的概念,分别是 Project 和 Task,Project 表示一个正在构建的项目,而 Task 表示某一个具体的任务。
-
Project
Project 表示正在构建的项目,每个 Project 都对应一个我们在 setting.gradle 中配置的 Project,除此之外还有一个 Root Project。 -
Task
Task 定义了一个当前任务执行时的最小单元,一个 Project 中一般会存在很多个 Task,通过执行这些 Task 来完成整个项目的构建。也就是说,项目构建的实际工作是由一个个的 Task 来完成的。Task有下列特征:可以依赖于别的 Task;不同时机的 Task 动作:onConfig(配置块)、doFirst、doLast、action;输入/输出;一些 getter/setter 属性。
E. Gradle中的sourceCompatibility
Gradle中有两个属性,分别是sourceCompatibility和targetCompatibility。
简单的说,sourceCompatibility属性跟编译环境有关,而targetCompatibility属性跟运行环境有关。
至少有这么几个原则,是不能违背的:
- sourceCompatibility关系到你使用到的Java语法特性及库
- sourceCompatibility不能比targetCompatibility大
- targetCompatibility不能比目标客户端运行环境的JavaVersion大
- targetCompatibility不能比当前Gradle使用的JavaVersion大
总结起来就是这样
代码用的语言特性对应的JavaVersion
≦ sourceCompatibility
≦ targetCompatibility
≦ Gradle使用的JavaVersion
≦ 客户端环境的JavaVersion
F. Gradle 生命周期
-
初始化
在初始化阶段,Gradle 会解析 setting.gradle 文件获取该项目包含几个子项目,然后创建一个 RootProject 以及分别为子项目创建 Project 实例。 -
配置
初始化完成后进入配置阶段,此时会加载所有 build.gradle 文件配置及插件,然后执行所有 Task 的配置代码块。 -
执行
执行指的就是依据顺序执行所有 Task 的动作。
需要注意,无论我们是单独运行某一个 Task,还是运行所有的 Task,Gradle 的生命周期都是固定为上述的三个步骤,只不过执行的时候会有选择的执行指定 Task 及其依赖的 Task,这意味着如果一个 Task 设置了在配置阶段执行某项任务,即使我们运行了别的 Task,该任务也会被执行。