Gradle

Gradle是一个基于JVM的构建工具,它提供了声明性构建、灵活的构建结构、深度API以及强大的多项目构建支持。通过Groovy DSL,Gradle允许自定义构建流程,包括依赖管理、多任务交互和多项目依赖。本文涵盖了Gradle的安装、基本概念如Projects和Tasks,Java构建入门,依赖管理以及Web工程构建,旨在帮助开发者全面理解并高效使用Gradle。

Gradle

Gradle是什么

Gradle,是一个基于JVM的富有突破性的构建工具,Gradle正迅速成为许多开源项目的前沿企业构建系统的选择,同时也在挑战遗留的自动化构建项目.

Gradle版本信息

工具版本信息
Gradle1.5

Gradle概述

基于声明的构建和基于约定的构建

Gradle的核心在于基于Groovy的丰富而可扩展的域描述语言(DSL),Groovy通过声明性的语言元素将基于声明的构建推向下层,你可以按你想要的方式进行组合,这些元素同样也为支持Java,Groovy,OSGi,Web,Scala项目提供了基于约定的构建,并且,这种声明性的语言是可以扩展的,你可以添加新的或增强现有的语言你元素,因此,它提供了简明,可维护和易理解的构建.

为以依赖为基础的编程方式提供语言支持

声明性语言优点在于通用任务图,你可以将其充分利用在构建中. 它提供了最大限度的灵活性,以让 Gradle 适应你的特殊需求。

构建结构化

Gradle 的灵活和丰富性最终能够支持在你的构建中应用通用的设计模式。 例如,它可以很容易地将你的构建拆分为多个可重用的模块,最后再进行组装,但不要强制地进行模块的拆分。 不要把原本在一起的东西强行分开(比如在你的项目结构里),从而避免让你的构建变成一场噩梦。 最后,你可以创建一个结构良好,易于维护,易于理解的构建。

深度API

Gradle允许你在构建执行的整个生命周期,对他核心配置以及执行行为进行监视并自定义

Gradle的扩展

Gradle有非常好的扩展性,从而简化项目的构建,到庞大的多项目构建,他都能显著的提升你的效率,这才十四真正的结构化构建,通过最先进的增量构建功能,它可以解决许多大型企业所面临的性能瓶颈问题.

多项目构建

Gradle 对多项目构建的支持非常出色。项目依赖是首先需要考虑的问题。 我们允许你在多项目构建当中对项目依赖关系进行建模,因为它们才是你真正的问题域。 Gradle 遵守你的布局。

Gradle 提供了局部构建的功能。 如果你在构建一个单独的子项目,Gradle 也会帮你构建它所依赖的所有子项目。 你也可以选择重新构建依赖于特定子项目的子项目。 这种增量构建将使得在大型构建任务中省下大量时间。

多种方式管理依赖

不同的团队喜欢用不同的方式来管理他们的外部依赖。 从 Maven 和 Ivy 的远程仓库的传递依赖管理,到本地文件系统的 jar 包或目录,Gradle 对所有的管理策略都提供了方便的支持。

Gradle是第一个构建集成工具

Ant tasks 是最重要的。而更有趣的是,Ant projects 也是最重要的。 Gradle 对任意的 Ant 项目提供了深度导入,并在运行时将 Ant 目标(target)转换为原生的 Gradle 任务(task)。 你可以从 Gradle 上依赖它们(Ant targets),增强它们,甚至在你的 build.xml 上定义对 Gradle tasks 的依赖。Gradle 为属性、路径等等提供了同样的整合。

Gradle 完全支持用于发布或检索依赖的 Maven 或 Ivy 仓库。 Gradle 同样提供了一个转换器,用于将一个 Maven pom.xml 文件转换为一个 Gradle 脚本。Maven 项目的运行时导入的功能将很快会有。

易于移植

Gradle 能适应你已有的任何结构。因此,你总可以在你构建项目的同一个分支当中开发你的 Gradle 构建脚本,并且它们能够并行进行。 我们通常建议编写测试,以保证生成的文件是一样的。 这种移植方式会尽可能的可靠和减少破坏性。这也是重构的最佳做法。

Groovy

Gradle 的构建脚本是采用 Groovy 写的,而不是用 XML。 但与其他方法不同,它并不只是展示了由一种动态语言编写的原始脚本的强大。 那样将导致维护构建变得很困难。 Gradle 的整体设计是面向被作为一门语言,而不是一个僵化的框架。 并且 Groovy 是我们允许你通过抽象的 Gradle 描述你个人的 story 的黏合剂。 Gradle 提供了一些标准通用的 story。这是我们相比其他声明性构建系统的主要特点。 我们的 Groovy 支持也不是简单的糖衣层,整个 Gradle 的 API 都是完全 groovy 化的。只有通过 Groovy才能去运用它并对它提高效率。

The Gradle Wrapper

Gradle Wrapper 允许你在没有安装 Gradle 的机器上执行 Gradle 构建。 这一点是非常有用的。比如,对一些持续集成服务来说。 它对一个开源项目保持低门槛构建也是非常有用的。 Wrapper 对企业来说也很有用,它使得对客户端计算机零配置。 它强制使用指定的版本,以减少兼容支持问题

自由和开源

Gradle 是一个开源项目,并遵循 ASL 许可。

为什么使用Groovy?

我们认为内部 DSL(基于一种动态语言)相比 XML 在构建脚本方面优势非常大。它们是一对动态语言。 为什么使用 Groovy?答案在于 Gradle 内部的运行环境。 虽然 Gradle 核心目的是作为通用构建工具,但它还是主要面向 Java 项目。 这些项目的团队成员显然熟悉 Java。我们认为一个构建工具应该尽可能地对所有团队成员透明。

你可能会想说,为什么不能使用 Java 来作为构建脚本的语言。 我认为这是一个很有意义的问题。对你们的团队来讲,它确实会有最高的透明度和最低的学习曲线。 但由于 Java 本身的局限性,这种构建语言可能就不会那样友善、 富有表现力和强大。 [1] 这也是为什么像 Python,Groovy 或者 Ruby 这样的语言在这方面表现得更好的原因。 我们选择了 Groovy,因为它向 Java 人员提供了目前为止最大的透明度。 其基本的语法,类型,包结构和其他方面都与 Java 一样,Groovy 在这之上又增加了许多东西。但是和 Java 也有着共同点。

对于那些分享和乐于去学习 Python 知识的 Java 团队而言,上述论点并不适用。 Gradle 的设计非常适合在 JRuby 或 Jython 中创建另一个构建脚本引擎。 那时候,对我们而言,它只是不再是最高优先级的了。我们很高兴去支持任何社区努力创建其他的构建脚本引擎。

Gradle安装

1.确定是否安装JDK Win10系统

在命令行输入 java -version可查询当前电脑已安装的版本

2.下载 从Gralde官方下载 Gradle | Releases

3.解压 Gradle发行包是一个ZIP文件

4.配置环境变量 运行Gradle必须将GRADLE_HOME/bin加入到你的PATH环境变量中

5.测试安装 运行 gradle -v

6.JVM参数配置

Gradle 运行时的 JVM 参数可以通过 GRADLE_OPTS 或 JAVA_OPTS 来设置.这些参数将会同时生效。 JAVA_OPTS 设置的参数将会同其它 JAVA 应用共享,一个典型的例子是可以在 JAVA_OPTS 中设置代理和 GRADLE_OPTS 设置内存参数。同时这些参数也可以在 gradle 或者 gradlew 脚本文件的开头进行设置。

Gradle构建基础

Projects和Tasks

projects 和 tasks是 Gradle 中最重要的两个概念。

任何一个 Gradle 构建都是由一个或多个 projects 组成。每个 project 包括许多可构建组成部分。 这完全取决于你要构建些什么。举个例子,每个 project 或许是一个 jar 包或者一个 web 应用,它也可以是一个由许多其他项目中产生的 jar 构成的 zip 压缩包。一个 project 不必描述它只能进行构建操作。它也可以部署你的应用或搭建你的环境。不要担心它像听上去的那样庞大。 Gradle 的 build-by-convention 可以让您来具体定义一个 project 到底该做什么。

每个 project 都由多个 tasks 组成。每个 task 都代表了构建执行过程中的一个原子性操作。如编译,打包,生成 javadoc,发布到某个仓库等操作。

到目前为止,可以发现我们可以在一个 project 中定义一些简单任务,后续章节将会阐述多项目构建和多项目多任务的内容。

Hello World

你可以通过在命令行运行 gradle 命令来执行构建,gradle 命令会从当前目录下寻找 build.gradle 文件来执行构建。我们称 build.gradle 文件为构建脚本。严格来说这其实是一个构建配置脚本,后面你会了解到这个构建脚本定义了一个 project 和一些默认的 task。

你可以创建如下脚本到 build.gradle 中 To try this out,create the following build script named build.gradle。

第一个构建脚本

build.gradle

task hello{
	doLast{
	println 'Hello World!'
	}
}
// 然后在该文件所在的目录执行gradle -q hello
// -q参数的作用是什么?
// 该文档的示例中很多地方在调用 gradle 命令时都加了 -q 参数。该参数用来控制 gradle 的日志级别,可以保证只输出我们需要的内容。具体可参阅本文档第十八章日志来了解更多参数和信息

执行脚本

OutPut of gradle -q hello
> gradle -q hello
Hello World!
// 上面的脚本定义了一个叫做 hello 的 task,并且给它添加了一个动作。当执行 gradle hello 的时候, Gralde 便会去调用 hello 这个任务来执行给定操作。这些操作其实就是一个用 groovy 书写的闭包。如果你觉得它看上去跟 Ant 中的 targets 很像,那么是对的。Gradle 的 tasks 就相当于 Ant 中的 targets。不过你会发现他功能更加强大。我们只是换了一个比 target 更形象的另外一个术语。不幸的是这恰巧与 Ant 中的术语有些冲突。ant 命令中有诸如 javac、copy、tasks。所以当该文档中提及 tasks 时,除非特别指明 ant task。否则指的均是指 Gradle 中的 tasks。

快速定义任务

build.gradle

task hello{
println 'Hello World!'
}
// 上面的脚本又一次采用闭包的方式来定义了一个叫做 hello 的任务,本文档后续章节中我们将会更多的采用这种风格来定义任务。
//注:<<在Gradle4.x中被弃用,在Gradle 5.0中被移除,详情见:Gradle 4.x官网
//例:task <<{ println 'Hello world!'}    解决方法:直接去掉或使用doLast解决。

代码及脚本

Gradle 脚本采用Groovy 书写.

在gradle任务中采用groovy

build.gradle

task upper << {
    String someString = 'mY_nAmE'
    println "Original: " + someString
    println "Upper case: " + someString.toUpperCase()
}
Output of gradle -q upper
> gradle -q upper
Original: mY_nAmE
Upper case: MY_NAME

或者

在gradle任务中采用groovy

build.gradle

task count << {
    4.times { print "$it " }
}
Output of gradle -q count
> gradle -q count
0 1 2 3

任务依赖

你可以按一下的方式进行创建任务间的依赖关系

在两个任务之间指明依赖关系

build.gradle

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

gradle -q intro的输出结果

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

添加依赖task也可以不必首先声明被依赖的task

延迟依赖

build.gradle

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

Output of gradle -q taskX

 \> gradle -q taskX
taskY
taskX

可以看到,taskX 是 在 taskY 之前定义的,这在多项目构建中非常有用。

注意:当引用的任务尚未定义的时候不可使用短标记法来运行任务。

动态任务

借助Groovy的强大不仅可以定义简单任务还能做更多的事

创建动态任务

build.gradle

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

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

Output of 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'
}
Output of 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的输出结果

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

对插件提供内置的任务

增加自定义属性

你可以为一个任务添加额外的属性,例如增加一个叫做myProperty的属性,用ext.myProperty的方式给他一个初始值,这样方便增加了一个自定义属性

为任务增加自定义属性

build.gradle

task myTask {
    ext.myProperty = "myValue"
}

task printTaskProperties << {
    println myTask.myProperty
}

gradle -q printTaskProperties输出结果

Output of gradle -q printTaskProperties
\> gradle -q printTaskProperties
myValue

调用Ant任务

Ant 任务是 Gradle 中的一等公民。Gradle 借助 Groovy 对 Ant 任务进行了优秀的整合。Gradle 自带了一个 AntBuilder,在 Gradle 中调用 Ant 任务比在 build.xml 中调用更加的方便和强大。 通过下面的例子你可以学到如何调用一个 Ant 任务以及如何与 Ant 中的属性进行通信。

利用AntBuilder执行ant.loadfile

build.gradle

task loadfile << {
    def files = file('../antLoadfileResources').listFiles().sort()
    files.each { File file ->
        if (file.isFile()) {
            ant.loadfile(srcFile: file, property: file.name)
            println " *** $file.name ***"
            println "${ant.properties[file.name]}"
        }
    }
}

gradle -q loadfile的输出结果

Output of gradle -q loadfile
\> gradle -q loadfile
*** agile.manifesto.txt ***
Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration  over contract negotiation
Responding to change over following a plan
 *** gradle.manifesto.txt ***
Make the impossible possible, make the possible easy and make the easy elegant.
(inspired by Moshe Feldenkrais)

方法抽取

利用方法组织脚本逻辑

build.gradle

task checksum << {
    fileList('../antLoadfileResources').each {File file ->
        ant.checksum(file: file, property: "cs_$file.name")
        println "$file.name Checksum: ${ant.properties["cs_$file.name"]}"
    }
}
task loadfile << {
    fileList('../antLoadfileResources').each {File file ->
        ant.loadfile(srcFile: file, property: file.name)
        println "I'm fond of $file.name"
    }
}
File[] fileList(String dir) {
    file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()
}

gradle -q loadfile的输出结果

Output of gradle -q loadfile
\> gradle -q loadfile
I'm fond of agile.manifesto.txt
I'm fond of gradle.manifesto.txt

定义默认任务

Gradle允许在脚本中定义多个默认任务

定义默认任务

build.gradle

defaultTasks 'clean', 'run'
task clean << {
    println 'Default Cleaning!'
}
task run << {
    println 'Default Running!'
}
task other << {
    println "I'm not a default task!"
}

gradle -q的输出结果

Output of gradle -q
\> gradle -q
Default Cleaning!
Default Running!

Configure by DAG

稍后会对 Gradle 的配置阶段和运行阶段进行详细说明 配置阶段后,Gradle 会了解所有要执行的任务 Gradle 提供了一个钩子来捕获这些信息。一个例子就是可以检查已经执行的任务中有没有被释放。借由此,你可以为一些变量赋予不同的值。

依赖任务的不同输出

build.gradle

task distribution << {
    println "We build the zip with version=$version"
}
task release(dependsOn: 'distribution') << {
    println 'We release now'
}
gradle.taskGraph.whenReady {taskGraph ->
    if (taskGraph.hasTask(release)) {
        version = '1.0'
    } else {
        version = '1.0-SNAPSHOT'
    }
}

gradle -q distrbution的输出结果

Output of gradle -q distribution
\> gradle -q distribution
We build the zip with version=1.0-SNAPSHOT

gradle -q release的输出结果

Output of gradle -q release
\> gradle -q release
We build the zip with version=1.0
We release now

whenReady 会在已发布的任务之前影响到已发布任务的执行。即使已发布的任务不是主要任务(也就是说,即使这个任务不是通过命令行直接调用)

Gradle Java构建入门

Java构建入门

Java插件

如你所见,Gradle 是一个通用工具。它可以通过脚本构建任何你想要实现的东西,真正实现开箱即用。但前提是你需要在脚本中编写好代码才行。

大部分 Java 项目基本流程都是相似的:编译源文件,进行单元测试,创建 jar 包。使用 Gradle 做这些工作不必为每个工程都编写代码。Gradle 已经提供了完美的插件来解决这些问题。插件就是 Gradle 的扩展,简而言之就是为你添加一些非常有用的默认配置。Gradle 自带了很多插件,并且你也可以很容易的编写和分享自己的插件。Java plugin 作为其中之一,为你提供了诸如编译,测试,打包等一些功能。

Java 插件为工程定义了许多默认值,如Java源文件位置。如果你遵循这些默认规则,那么你无需在你的脚本文件中书写太多代码。当然,Gradle 也允许你自定义项目中的一些规则,实际上,由于对 Java 工程的构建是基于插件的,那么你也可以完全不用插件自己编写代码来进行构建。

后面的章节我们通过许多深入的例子介绍了如何使用 Java 插件来进行以来管理和多项目构建等。但在这个章节我们需要先了解 Java 插件的基本用法。

一个基本的Java项目

采用Java插件

build.gradle
apply plugin:'java'
    
    // 示例代码可以在Gradle发行包中的samples/java/quickstart定义一个Java项目只需要如此而已,这将会为你添加Java插件以及其一些内置任务

标准目录结构如下

project
	+build
	+src/main/java
	+src/main/resources
	+src/test/java
	+src/test/resources

Gradle 默认会从 src/main/java 搜寻打包源码,在 src/test/java 下搜寻测试源码。并且 src/main/resources 下的所有文件按都会被打包,所有 src/test/resources 下的文件 都会被添加到类路径用以执行测试。所有文件都输出到 build 下,打包的文件输出到 build/libs 下

构建项目

Java 插件为你添加了众多任务。但是它们只是在你需要构建项目的时候才能发挥作用。最常用的就是 build 任务,这会构建整个项目。当你执行 gradle build 时,Gralde 会编译并执行单元测试,并且将 src/main/* 下面 class 和资源文件打包。

构建Java项目

运行gradle build的输出结果

Output of gradle build
> gradle build
:compileJava
:processResources
:classes
:jar
:assemble
:compileTestJava
:processTestResources
:testClasses
:test
:check
:build
BUILD SUCCESSFUL
Total time: 1 secs

clean

删除build目录以及所有构建完成的文件

assemble

编译并打包Jar文件,但不会执行单元测试,一些其他插件可能会增强这个任务的功能。例如,如果采用了 War 插件,这个任务便会为你的项目打出 War 包。

check

编译并测试代码。一些其他插件也可能会增强这个任务的功能。例如,如果采用了 Code-quality 插件,这个任务会额外执行 Checkstyle。

外部依赖

通常,一个 Java 项目拥有许多外部依赖。你需要告诉 Gradle 如何找到并引用这些外部文件。在 Gradle 中通常 Jar 包都存在于仓库中。仓库可以用来搜寻依赖或发布项目产物。下面是一个采用 Maven 仓库的例子

添加Maven仓库

build.gradle
repositories{
	mavenCentral()
}

添加外部依赖,这里声明了编译所需依赖commons-collections和测试所需依赖Junit

添加依赖

build.gradle
dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

自定义项目

Java 插件为你的项目添加了众多默认配置。这些默认值通常对于一个普通项目来说已经足够了。但如果你觉得不适用修改起来也很简单。看下面的例子,我们为 Java 项目指定了版本号以及所用的 JDK 版本,并且添加一些属性到 mainfest 中。

自定义MANIFEST.MF

build.gradle
sourceCompatibility = 1.5
version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
    }
}

Java 插件添加的都是一些普通任务,如同他们写在 Build 文件中一样。这意味着前面章节展示的机制都可以用来修改这些任务的行为。例如,可以设置任务的属性,添加任务行为,更改任务依赖,甚至是重写覆盖整个任务。在下面的例子中,我们将修改 test 任务,这是一个 Test 类型任务。让我们来在它执行时为它添加一些系统属性。

为test添加系统属性

build.gradle
test {
    systemProperties 'property': 'value'
}

发布Jar包

build.gradle
uploadArchives {
    repositories {
       flatDir {
           dirs 'repos'
       }
    }
}

执行gradle uploadArchives发布Jar包

创建Eclipse文件

若要把项目导入Eclipse中,你需要添加另外一个插件到你的脚本文件中

Eclipse plugin

build.gradle
apply plugin 'eclipse'

执行gradle eclipse来生成Eclipse项目文件

多项目构建-项目结构

Build layout
multiproject/
  api/
  services/webservice/
  shared/

此处有三个工程。api 工程用来生成给客户端用的 jar 文件,这个 jar 文件可以为 XML webservice 提供 Java 客户端。webservice 是一个 web 应用,生成 XML。shared 工程包含的是前述两个工程共用的代码。

多项目构建定义

定义一个多项目构建工程需要在根目录(本例中与 multiproject 同级)创建一个setting 配置文件来指明构建包含哪些项目。并且这个文件必需叫 settings.gradle 本例的配置文件如下:

多项目构建中的settings.gradle

settings.gradle
include "shared", "api", "services:webservice", "services:shared"

公共配置

对多项目构建而言,总有一些共同的配置.在本例中,我们会在根项目上采用配置注入的方式定义一些公共配置。根项目就像一个容器,子项目会迭代访问它的配置并注入到自己的配置中。这样我们就可以简单的为所有工程定义主配置单了:

多项目构建-公共配置

build.gralde
subprojects {
    apply plugin: 'java'
    apply plugin: 'eclipse-wtp'
    repositories {
       mavenCentral()
    }
    dependencies {
        testCompile 'junit:junit:4.11'
    }
    version = '1.0'
    jar {
        manifest.attributes provider: 'gradle'
    }
}

工程依赖

同一个构建中可以建立工程依赖,一个工程的 jar 包可以提供给另外一个工程使用。例如我们可以让 api 工程以依赖于 shared 工程的 jar 包。这样 Gradle 在构建 api 之前总是会先构建 shared 工程。

多项目构建-工程依赖

api/build.gradle
dependencies{
	compile project(':shared')
}

打包发布

多项目构建-发布

api/build.gradle
task dist(type: Zip) {
    dependsOn spiJar
    from 'src/dist'
    into('libs') {
        from spiJar.archivePath
        from configurations.runtime
    }
}
artifacts {
   archives dist
}

Gradle依赖管理基础

什么是依赖管理

通俗来讲,依赖管理由如下两部分组成。首先,Gradle 需要知道项目构建或运行所需要的一些文件,以便于找到这些需要的文件。我们称这些输入的文件为项目的依赖。其次,你可能需要构建完成后自动上传到某个地方。我们称这些输出为发布。下面来仔细介绍一下这两部分:

大部分工程都不太可能完全自给自足,一般你都会用到其他工程的文件。比如我工程需要 Hibernate 就得把它的类库加进来,比如测试的时候可能需要某些额外 jar 包,例如 JDBC 驱动或 Ehcache 之类的 Jar 包。

这些文件就是工程的依赖。Gradle 需要你告诉它工程的依赖是什么,它们在哪,然后帮你加入构建中。依赖可能需要去远程库下载,比如 Maven 或者 Ivy 库。也可以是本地库,甚至可能是另一个工程。我们称这个过程叫依赖解决

通常,依赖的自身也有依赖。例如,Hibernate 核心类库就依赖于一些其他的类库。所以,当 Gradle 构建你的工程时,会去找到这些依赖。我们称之为依赖传递

大部分工程构建的主要目的是脱离工程使用。例如,生成 jar 包,包括源代码、文档等,然后发布出去。

这些输出的文件构成了项目的发布内容。Gralde 也会为你分担这些工作。你声明了发布到到哪,Gradle 就会发布到哪。“发布”的意思就是你想做什么。比如,复制到某个目录,上传到 Maven 或 Ivy 仓库。或者在其它项目里使用,这些都可以称之为发行

依赖声明

build.gradle

apply plugin: 'java'
repositories {
    mavenCentral()
}
dependencies {
    compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

首先,Hibernate-code 3.6.7.Final.jar是编译器必需的依赖,并且这些相关的依赖也会一并被加载进来,这段脚本同时还有声明项目测试阶段需要4.0版本以上的Junit同事告诉Gradle可以去Maven中央仓库去找这些依赖.

依赖配置

Gradle 中依赖以组的形式来划分不同的配置。每个配置都只是一组指定的依赖。我们称之为依赖配置 。你也可以借由此声明外部依赖。后面我们会了解到,这也可用用来声明项目的发布。

Java 插件定义了许多标准配置项。这些配置项形成了插件本身的 classpath。比如下面罗列的这一些,并且你可以从 “Java 插件 - 依赖配置”了解到更多详细内容.。

compile

编译范围依赖在所有的calsspath中可用,同时他们也会被打包

runtime

runtime依赖在运行和测试系统的时候需要,但在编译的时候不需要,比如你可能在编译的时候只需要JDBC API JAR,而且只有在运行的时候才需要JDBC驱动实现

testCompile

测试期编译需要附加的依赖

testRuntime

测试运行期需要

不同的插件提供了不同的标准配置,你甚至可以定义属于自己的配置项

外部依赖

依赖的类型有很多种,其中有一种类型称之为外部依赖。这种依赖由外部构建或者在不同的仓库中,例如 Maven 中央仓库或 Ivy 仓库中抑或是本地文件系统的某个目录中。

定义外部依赖需要像下面这样进行依赖配置

定义外部依赖

build.gradle

dependencies {
    compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
}

外部依赖包含group,name和version几个属性,根据仓库的不同,group和cersion也可能是可选的.

当然,也有一种更加简洁的方式来声明外部依赖。采用:将三个属性拼接在一起即可。“group:name:version”

快速定义外部依赖

build.gradle

dependencies{
	compile"org.hibernate:hibernate-core:3.6.7.Final"
}

仓库

Gradle 是在一个被称之为仓库的地方找寻所需的外部依赖。仓库即是一个按 group,name 和 version 规则进行存储的一些文件。Gradle 可以支持不同的仓库存储格式,如 Maven 和 Ivy,并且还提供多种与仓库进行通信的方式,如通过本地文件系统或 HTTP。

默认情况下,Gradle 没有定义任何仓库,你需要在使用外部依赖之前至少定义一个仓库,例如 Maven 中央仓库。

使用Maven中央仓库

build.gradle

repositories{
	mavenCentral()
}

使用Maven远程仓库

repositories {
    maven {
        url "http://repo.mycompany.com/maven2"
    }
}

采用lvy远程仓库

repositories {
    ivy {
        url "http://repo.mycompany.com/repo"
    }
}

采用本地lvy目录

repositories {
    ivy {
        // URL can refer to a local directory
        url "../local-repo"
    }
}

打包发布

依赖配置也被用于发布文件[3]我们称之为打包发布发布

插件对于打包提供了完美的支持,所以通常而言无需特别告诉 Gradle 需要做什么。但是你需要告诉 Gradle 发布到哪里。这就需要在 uploadArchives 任务中添加一个仓库。下面的例子是如何发布到远程 Ivy 仓库的:

//发布到lvy仓库
uploadArchives {
    repositories {
        ivy {
            credentials {
                username "username"
                password "pw"
            }
            url "http://repo.mycompany.com"
        }
    }
}
/**
执行 gradle uploadArchives,Gradle 便会构建并上传你的 jar 包,同时会生成一个 ivy.xml 一起上传到目标仓库。

当然你也可以发布到 Maven 仓库中。语法只需稍微一换就可以了。[4]

p.s:发布到 Maven 仓库你需要 Maven 插件的支持,当然,Gradle 也会同时产生 pom.xml 一起上传到目标仓库。
*/
//发布到Maven仓库
apply plugin: 'maven'
uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: "file://localhost/tmp/myRepo/")
        }
    }
}

Gradle Web工程构建

Web工程构建

Gradle 为 Web 开发提供了两个主要插件,War plugin 和 Jetty plugin。 其中 War plugin 继承自 Java plugin,可以用来打 war 包。jetty plugin 继承自 War plugin 作为工程部署的容器。

打War包

需要打包War文件,需要在脚本中使用War Plugin

War Plugin

build.gradle

apply plugin:"war"
    /**
    本示例代码可以在 Gradle 发行包中的 samples/webApplication/quickstart 路径下找到。
由于继承自 Java 插件,当你执行 gradle build 时,将会编译、测试、打包你的工程。Gradle 会在 src/main/webapp 下寻找 Web 工程文件。编译后的 classes 文件以及运行时依赖也都会被包含在 War 包中。
Groovy web构建
在一个工程中你可以采用多个插件。比如你可以在 web 工程中同时使用 War plugin 和 Groovy plugin。插件会将 Gradle 依赖添加到你的 War 包中。
    */

Web工程启动

要启动Web工程,只需要使用Jetty Plugin即可

采用Jetty Plugin启动Web工程

build.gradle

apply plugin:"jetty"
    /**
    由于 Jetty plugin 继承自 War plugin。调用 gradle jettyRun 将会把你的工程启动部署到 jetty 容器中。调用 gradle jettyRunWar 会打包并启动部署到 jetty 容器中。
待添加:使用哪个 URL,配置端口,使用源文件的地方,可编辑你的文件,以及重新加载的内容。
    */

Gradle Gradle命令行的基本使用

多任务调用

你可以以列表的形式在命令行中一次调用多个任务。例如 gradle compile test 命令会依次调用,并且每个任务仅会被调用一次。compile 和 test 任务以及它们的依赖任务。无论它们是否被包含在脚本中:即无论是以命令行的形式定义的任务还是依赖于其它任务都会被调用执行。来看下面的例子。

下面定义了四个任务。dist 和 test 都依赖于 compile,只用当 compile 被调用之后才会调用 gradle dist test 任务

任务依赖

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W79v8hX6-1659080110485)(D:\A-My Data\MarkDown\Java.assets\image-20220725092624793.png)]

build.gradle

task compile << {
    println 'compiling source'
}
task compileTest(dependsOn: compile) << {
    println 'compiling unit tests'
}
task test(dependsOn: [compile, compileTest]) << {
    println 'running unit tests'
}
task dist(dependsOn: [compile, test]) << {
    println 'building the distribution'
}

Gradle dist test的输出结果

\> gradle dist test
:compile
compiling source
:compileTest
compiling unit tests
:test
running unit tests
:dist
building the distribution
BUILD SUCCESSFUL
Total time: 1 secs

由于每个任务仅会被调用一次,所以调用Gradle dist test与调用gradle test效果是相同的

排除任务

可以执行命令-x来排除某些任务

gradle dist -x test的输出结果

\> gradle dist -x test
:compile
compiling source
:dist
building the distribution
BUILD SUCCESSFUL
Total time: 1 secs

可以看到,test 任务并没有被调用,即使他是 dist 任务的依赖。同时 test 任务的依赖任务 compileTest 也没有被调用,而像 compile 被 test 和其它任务同时依赖的任务仍然会被调用。

简化任务名

当你试图调用某个任务的时候,无需输入任务的全名。只需提供足够的可以唯一区分出该任务的字符即可。例如,上面的例子你也可以这么写。用 gradle di 来直接调用 dist 任务。

gradle di的输出结果

\> gradle di
:compile
compiling source
:compileTest
compiling unit tests
:test
running unit tests
:dist
building the distribution
BUILD SUCCESSFUL
Total time: 1 secs

可以用驼峰命名的任务中每个单词的首字母进行调用,例如,可以执行gradle compTest or even gradle cT来调用compile Test任务

简化驼峰任务名

gradle cT的输出结果

\> gradle cT
:compile
compiling source
:compileTest
compiling unit tests
BUILD SUCCESSFUL
Total time: 1 secs

简化后任然可以使用-x参数

选择构建位置

调用gradle时,默认情况下总是会创建当前目录下的文件,可以使用-b参数选择构建的文件,并且当你使用此参数时setting.gradle将不会生效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值