Menu Close

使用 Gradle 快速构建 Java 项目(例一)

环境描述

描述项 内容
操作系统 CentOS Linux release 7.8.2003 (Core)
java版本 java version "1.8.0_161"
IDEA版本 2022.2.2
Gradle版本 7.5

1. Gradle的基本概念有哪些?

  1. 三级数据模型:Build,Project,Task。一个Build可以包括1到N个Project,一个Project包括1-N个Task;

  2. Task之间的关系是有向无环图(DAG),构建过程就是按照DAG依次执行其中的Task,Gradle可以看成指挥官,是Task的调度器;

  3. Plugin是底下真正干活的,不同的Plugin实现不同功能的Task,添加Plugin就会在Build中预定义Task和Configuration。

下图即是一个常规的Java项目Build过程经历的Task,像jar/classes等等这些Task的实现就是Java Plugin提供的。

file

gradle 可以类比做一条流水线,task 可以比作流水线上的机器人,每个机器人负责不同的事情,最终生成完整的构建产物:

file

2. Gradle的核心元素

2.1. Project

Gradle为每个module的 build.gradle 都会创建一个相应的Project领域对象,在编写gradle脚本的时候,我们实际上是在操作诸如Project这样的Gradle领域对象。
那么我们总共有多少个projects对象呢?projects对象的数量等于module的数量 + 1,也就是所有的 module + Root project。大家也可以使用命令行打印出来看一下:./gradlew projects

2.2. Task

一个Project由一个或多个Task组成,它是构建过程中的原子任务,可以使编译class、上传jar包等。在定义一个Task的时候,需要的参数如下:

参数 含义 默认值
name task的名字 不能为空,必须指定
type task的“父类” DefaultTask
overwrite 是否替换已经存在的task false
dependsOn task依赖的task集合 []
group task属于哪个组 null
description task的描述 null

我们平时执行的最多的命令应该是 ./gradlew build 了吧,而这个命令可以说是最复杂的task命令了,我们也知道它每次都会执行很长时间,而这是因为build的task任务依赖了很多任务,它会把它所依赖的task执行完之后,才会执行自己的task。
定义一个task的方式有很多种,而task也分为两种类型:配置型Task和动作型Task。配置型Task会在Gradle的配置阶段执行,而动作型Task会在Gradle的执行阶段执行。

任务的生命周期如下:

file

3. 使用 Gradle 构建 Java 项目(Linux环境)

3.1. 初始化一个项目

1) 在根目录下输入以下命令创建一个叫做 basicDemo 文件夹

mkdir basicDemo

2) 进入创建的文件夹(下述其他操作均在该文件夹下)

cd basicDemo

3) 输入gradle初始化命令

gradle init

使用默认的选项,一路回车即可。

详细内容

[java@etdbmysql basicDemo]$ gradle init
Starting a Gradle Daemon (subsequent builds will be faster)

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 回车

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 回车

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] 回车
Project name (default: basicDemo): 回车

> Task :init
Get more help with your project: Learn more about Gradle by exploring our samples at https://docs.gradle.org/7.5/samples

BUILD SUCCESSFUL in 18s
2 actionable tasks: 2 executed

4) 执行成功后使用 ls 或 tree 命令查看目录结构

tree

file

3.2. 创建一段代码

1) 创建主程序目录结构

mkdir -p src/main/java/xin/qishuo/basicDemo

2) 编写Java文件

vim src/main/java/xin/qishuo/basicDemo/Example.java

3) 创建Java代码

package xin.qishuo.basicDemo;

public class Example {
  public String getGreeting() {
     return "Hello World!";
   }

  public static void main(String[] args) {
    System.out.println(new Example().getGreeting());
  }
}

3.3. 创建一个task (任务)

1)task简介
Gradle提供API,用于通过基于Groovy或Kotlin的DSL创建和配置任务。 项目包括一组任务,每个任务执行一些基本操作。

Gradle附带了一个可以在您自己的项目中配置的任务库。 例如,有一种名为Copy的核心类型,它将文件从一个位置复制到另一个位置。 复制任务非常有用(有关详细信息,请参阅官方文档:Gradle DSLs and API/Groovy DSL Reference/Task types),下面给出一下简单示例。

2)创建一个Copy的Task

在构建文件中定义一个名为Copy的类型的副本(注意大写字母),该任务将src目录复制到名为dest的新目录。 (您不必创建dest目录,任务将为您完成。)

  • build.gradle(Groovy语法)

    task copy(type: Copy, group: "Custom", description: "Copies sources to the dest directory") {
    from "src"
    into "dest"
    }
  • build.gradle.kts(Kotlin语法)

    tasks.create<Copy>("copy") {
    description = "Copies sources to the dest directory"
    group = "Custom"
    
    from("src")
    into("dest")
    }

在这里,group和description可以是您想要的任何内容。 您甚至可以省略它们,但这样做也会在以后使用的任务报告中省略它们。

3)查看Task

./gradlew tasks --all

file

4)执行Task

./gradlew copy

5)最后检查是否生成了dest目录及copy的文件

3.4. 使用插件

Gradle包含一系列插件,Gradle插件门户网站上提供了许多插件。 该发行版附带的插件之一是 base 插件。 结合名为Zip的核心类型,您可以使用配置的名称和位置创建项目的zip存档。

使用插件语法将基本插件添加到构建脚本文件中。 请务必在文件顶部添加插件 {} 块。

  • build.gradle(Groovy语法)

    plugins {
    id "base"
    }
  • build.gradle.kts(Kotlin语法)

    plugins {
    id("base")
    }

现在添加一个从src目录创建zip存档的任务。

  • build.gradle(Groovy语法)

    task zip(type: Zip, group: "Archive", description: "Archives sources in a zip file") {
    from "src"
    setArchiveName "basicDemo-1.0.zip"
    }
  • build.gradle.kts(Kotlin语法)

    tasks.create<Zip>("zip") {
    description = "Archives sources in a zip file"
    group = "Archive"
    
    from("src")
    setArchiveName("basicDemo-1.0.zip")
    }

基本插件会在 build/distributions 文件夹中创建一个名为basicDemo-1.0.zip的存档文件。

1)查看任务

./gradlew tasks --all

file

在添加插件 basic 后,task 多出了 Build tasksVerification tasks任务。

2)运行新的zip任务

./gradlew zip

3)如果移除 base 插件再执行 gradlew zip 就会出错

file

4)修改 build.gradle 文件

  • build.gradle(Groovy语法)
task zip(type: Zip) {
  from "src"
  archiveFileName = "basicDemo-2.0.zip"
  destinationDirectory = file('./dest')
}

3.5. Application插件

Application插件是Gradle的核心插件,它定义了一系列现成的任务,可帮助我们打包和分发我们的应用程序。
使用方法参见官方文档:https://docs.gradle.org/current/userguide/application_plugin.html

1)使用application插件

  • build.gradle(Groovy语法)

    plugins {
    id 'application'
    }
  • build.gradle.kts(Kotlin语法)

    plugins {
    application
    }

2)查看所有的Task

./gradlew tasks --all

file

在添加插件 application 后,task 多出了 Application tasksDistribution tasks 以及 Documentation tasks 任务。

3)执行 build 命令

./gradlew build

file

4)运行编译后的 jar 包

java -cp ./build/libs/basicDemo.jar xin.qishuo.basicDemo.Example

file

5)使用 gradle run 却报错

./gradlew run

file

因为没有指定主类,并且类路径不是可执行的 jar。

6)指定项目的javaMainClass

  • build.gradle(Groovy语法,要特别注意大小写敏感
application {
 mainClassName = 'xin.qishuo.basicDemo.Example'
}

7)再次执行 run 命令

./gradlew run

file

8)使用JavaExec任务运行

  • build.gradle(Groovy语法)
plugins {
  id 'java'
}

task runWithJavaExec(type: JavaExec) {
  group = "Execution"
  description = "Run the main class with JavaExecTask"
  classpath = sourceSets.main.runtimeClasspath
  mainClass = 'xin.qishuo.basicDemo.Example'
}
  • 查看task
./gradlew tasks --all

file

  • 运行task
./gradlew runWithJavaExec

file

任务类型 JavaExec 的详细介绍见 官网说明

附录

附录A. 相关联的文章

附录B. 参考

Gradle的生命周期详解
https://juejin.cn/post/7067719629874921508

Gradle 的下载安装配置以及创建第一个Gradle 项目:
https://www.cnblogs.com/xingyunblog/p/10428178.html

附录C. gradle 主要要点

file