构建工具Gradle的使用


构建工具Gradle的使用

构建工具的作用

​ 依赖管理;测试、打包、发布;机器能干的活,绝不自己动手。

主流构建工具:

(1)Ant:编译、测试、打包;

(2)Maven:依赖管理、发布;

(3)Gradle:Groovy,具有更高的灵活性和可扩展性。

Gradle是什么?

一个开源的项目自动化构建工具,建立在Apache Ant和Apache Maven概念的基础上,并引入了基于Groovy的特定领域语言(DSL),而不再使用XML形式管理构建脚本。

Gradle能做什么?

进行依赖管理,自动化运行测试、打包,发布到指定的地方去。

准备工作

安装

1.确保已经安装JDK,java -version

2.从Gradle官网下载Gradle:[入口][https://gradle.org]

配置环境变量

  • 配置环境变量,GRADLE_HOME
  • 添加到path, %GRADLE_HOME%\bin
  • 验证是否安装成功, gradle -v

Groovy是什么?

Groovy是用于Java虚拟机的一种敏捷的动态语言,它是一种成熟的面向对象编程语言,既可以用于面向对象编程,又可以用作纯粹的脚本语言。使用该种语言不必编写过多的带麻,同时又具有闭包和动态语言中的其他特性。

Groovy与java比较

  1. Groovy完全兼容Java语法。
  2. 分号是可选的。
  3. 类、方法默认为public。
  4. 编译器会自动为属性生成get/set方法
  5. 属性可以用点来获取
  6. 用最后一个表达式的值作为返回值;
  7. ==等同于equals方法,不会有NullPointerExceptions

传统JavaBean写法

public class ProjectVersion{
    private int major;
    private int minor;

    ProjectVersion(int major, int minor) {
        this.major = major
        this.minor = minor
    }

    int getMajor() {
        return major
    }

    void setMajor(int major) {
        this.major = major
    }

    int getMinor() {
        return minor
    }

    void setMinor(int minor) {
        this.minor = minor
    }
}

Groovy写法

public class ProjectVersion{
    private int major;
    private int minor
    ProjectVersion(int major, int minor) {
        this.major = major
        this.minor = minor
    }
    int getMajor() {
        major
    }
    void setMajor(int major) {
        this.major = major
    }
}
// 测试一下
ProjectVersion v1 = new ProjectVersion(1,1);
println(v1.minor)
ProjectVersion v2 = null
println v2==v1

高效特性

1.assert语句
2.可选类型定义,弱类型,
3.可选的括号
4.字符串(单引号,双引号,三个单引号)
5.集合API
6.闭包

// groovy高效特性
// 1.可选的类型定义
def version = 1

// 2.任意的assert
assert version == 2

// 3.括号是可选的
println version

// 4. 字符串
def s1 = 'imooc'
def s2="gradle version is ${version}"
def s3 = '''my name 
is
 silvercorridors'''

println s1
println s2
println s3

// 5.集合api
def buildTools=['ant','maven']
buildTools << 'gradle'
assert buildTools.getClass() == ArrayList
assert buildTools.size() == 3

// map
def buildYears = ['ant':2000,'maven':2004]
buildYears.gradle = 2009
println buildYears.ant
println buildYears['gradle']
println buildYears.getClass()

// 6.闭包
def c1 = {
    v -> print v
}
def c2 = {
    print "hello"
}
def method1(Closure closure){
    closure('param')
}
def method2(Closure closure){
    closure()
}
method1(c1);
method2(c2);
// 输出结果 paramhello

Gradle项目

目录结构

构建方式

idea右侧有一个gradle窗口

1.jar用于将文件编译为jar包;
2.build会执行build.gradle文件,由于插件是Java,所以也会将文件编译为jar包;
3.classes会将文件转为class文件;
3.clean会清除操作

任务依赖

例子. 申明任务之间的依赖关系

build.gradle

task hello << {
    println 'Hello world!'
}

task intro(dependsOn: hello) << {
    println "I'm Gradle"
}

gradle -q intro 命令的输出

> gradle -q intro
Hello world!
I'm Gradle

intro 依赖于 hello, 所以执行 intro 的时候 hello 命令会被优先执行来作为启动 intro 任务的条件.

在加入一个依赖之前, 这个依赖的任务不需要提前定义, 来看下面的例子.

例子. Lazy dependsOn - 其他的任务还没有存在

build.gradle

task taskX(dependsOn: 'taskY') << {
    println 'taskX'
}
task taskY << {
    println 'taskY'
}

gradle -q taskX 命令的输出

> gradle -q taskX
taskY
taskX

taskX 到 taskY 的依赖在 taskY 被定义之前就已经声明了。

动态任务

Groovy 不仅仅被用来定义一个任务可以做什么. 举个例子, 你可以使用它来动态的创建任务.

例子 动态的创建一个任务

build.gradle

4.times { counter ->
    task "task$counter" << {
        println "I'm task number $counter"
    }
}

这里动态的创建了 task1, task2, task3, task4

gradle -q task1 命令的输出

> gradle -q task1
I'm task number 1

使用已经存在的任务

当任务创建之后, 它可以通过API来访问. 这个和 Ant 不一样. 举个例子, 你可以创建额外的依赖.

例子. 通过API访问一个任务 - 加入一个依赖

build.gradle

4.times { counter ->
    task "task$counter" << {
        println "I'm task number $counter"
    }
}
task0.dependsOn task2, task3

gradle -q task0 命令的输出

> gradle -q task0
I'm task number 2
I'm task number 3
I'm task number 0

或者你可以给一个已经存在的任务加入行为.

例子. 通过API访问一个任务 - 加入行为

build.gradle

task hello << {
    println 'Hello Earth'
}
hello.doFirst {
    println 'Hello Venus'
}
hello.doLast {
    println 'Hello Mars'
}
hello << {
    println 'Hello Jupiter'
}

gradle -q hello 命令的输出

> gradle -q hello
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter

doFirst 和 doLast 可以被执行许多次. 他们分别可以在任务动作列表的开始和结束加入动作. 当任务执行的时候, 在动作列表里的动作将被按顺序执行. 这里第四个行为中 << 操作符是 doLast 的简单别称.

短标记法

正如同你已经在之前的示例里看到, 有一个短标记 $ 可以访问一个存在的任务. 也就是说每个任务都可以作为构建脚本的属性:

例子. 当成构建脚本的属性来访问一个任务

build.gradle

task hello << {
    println 'Hello world!'
}
hello.doLast {
    println "Greetings from the $hello.name task."
}

gradle -q hello 命令的输出

> gradle -q hello
Hello world!
Greetings from the hello task.

这里的 name 是任务的默认属性, 代表当前任务的名称, 这里是 hello.

这使得代码易于读取, 特别是当使用了由插件(如编译)提供的任务时尤其如此.

自定义任务属性

你可以给任务加入自定义的属性. 列如加入一个叫做 myProperty 属性, 设置一个初始值给 ext.myProperty. 然后, 该属性就可以像一个预定义的任务属性那样被读取和设置了.

例子. 给任务加入自定义属性

build.gradle

task myTask {
    ext.myProperty = "myValue"
}

task printTaskProperties << {
    println myTask.myProperty
}

gradle -q printTaskProperties 命令的输出

> gradle -q printTaskProperties
myValue

给任务加自定义属性是没有限制的.

使用Gradle构建Java项目

使用Java插件

大都数 Java 项目是非常相像的: 你需要编译你的 Java 源文件, 运行一些单元测试, 同时创建一个包含你类文件的 JAR.

Gradle 通过使用插件解决了这个问题. 插件是 Gradle 的扩展, 它会通过某种方式配置你的项目, 典型的有加入一些预配置任务. Gradle 自带了许多插件, 你也可以很简单地编写自己的插件并和其他开发者分享它. Java 插件就是一个这样的插件. 这个插件在你的项目里加入了许多任务, 这些任务会编译和单元测试你的源文件, 并且把它们都集成一个 JAR 文件里.

使用Java插件,在新版的Gradle中我们要使用Java插件可以在build.gradle下如下编写:

plugins {
    id 'java-library'
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(11)
    }
}

version = '1.2.1'

通过应用 Java 库插件,您可以获得一大堆功能:

  • 编译src/main/javacompileJava下所有 Java 源文件的task
  • src/test/javacompileTestJava下源文件的一个task
  • 从src/test/javatest运行测试的task
  • src/main/resources中已编译的类和资源jar打包到名为<project>-<version>.jar的单个 JAR中的taskmain
  • 为类javadoc生成 Javadoc 的taskmain

通过 source sets声明源文件

Gradle 的 Java 支持率先引入了用于构建基于源的项目的新概念:源集。主要思想是源文件和资源通常按类型在逻辑上分组,例如应用程序代码、单元测试和集成测试。每个逻辑组通常都有自己的一组文件依赖项、类路径等。重要的是,形成源集的文件不必位于同一目录中

源集是一个强大的概念,它将编译的几个方面联系在一起:

  • 源文件及其所在位置
  • 编译类路径,包括任何必需的依赖项(通过 Gradle配置
  • 编译的类文件放置在哪里

关联方式:

java源码集合编译

依赖管理

绝大多数 Java 项目都依赖于库,因此管理项目的依赖关系是构建 Java 项目的重要部分。依赖管理是一个很大的话题,所以我们将在这里重点介绍 Java 项目的基础知识。如果您想深入了解细节,请查看依赖管理简介

为您的 Java 项目指定依赖项只需要三个信息:

  • 您需要哪个依赖项,例如名称和版本
  • 它需要什么,例如编译或运行
  • 在哪里寻找它

前两个在dependencies {}块中指定,第三个在repositories {}块中指定。例如,要告诉 Gradle 您的项目需要 3.6.7 版的Hibernate Core 来编译和运行您的生产代码,并且您想从 Maven 中央存储库下载该库,您可以使用以下片段:

示例:声明依赖项

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.hibernate:hibernate-core:3.6.7.Final'
}

这三个元素的 Gradle 术语如下:

Repository (ex: mavenCentral()) — 在哪里查找您声明为依赖项的模块。

配置(例如:implementation)——一个命名的依赖集合,为一个特定的目标组合在一起,例如编译或运行一个模块——一种更灵活的 Maven 范围形式。

模块坐标(ex: org.hibernate:hibernate-core-3.6.7.Final) — 依赖项的 ID,通常格式为 ‘ : : ‘(或Maven 术语中的 ‘ : : ‘)

就配置而言,主要感兴趣的是:

  • compileOnly— 对于编译生产代码所必需但不应成为运行时类路径的一部分的依赖项
  • implementation(取代compile) — 用于编译和运行时
  • runtimeOnly(取代runtime)——仅在运行时使用,不用于编译
  • testCompileOnly— 与compileOnly测试相同
  • testImplementation— 测试等效于implementation
  • testRuntimeOnly— 测试等效于runtimeOnly

注意,现在的版本gradle已经没有了compile配置。

为什么没有compile配置?

Java 库插件历来使用compile编译和运行项目生产代码所需的依赖项配置。它现在已被弃用,并且在使用时会发出警告,因为它不区分影响 Java 库项目的公共 API 的依赖项和不影响的依赖项。您可以在构建 Java 库中了解有关这种区别的重要性的更多信息。

参考资料

Gradle User Guide 中文版

Gradle官网用户手册


文章作者: 银色回廊
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 银色回廊 !
评论
  目录