Gradle探秘
在"系统属性对话框里"要设置环境变量和路径:
set M2_HOME=e:\WJW_APP\PStart\Java\maven3
set GRADLE_USER_HOME=z:\GRADLE_USER_HOME
set path=%path%;C:\ProgramData\Oracle\Java\javapath;c:\Java\jdk1.8\bin;e:\WJW_APP\PStart\Java\gradle\bin
设置
M2_HOME
是为了引用本地的maven仓库.
本地仓库默认在 /.m2/repository目录下,只需要添加如下脚本来引用它:repositories {
mavenLocal()
}
理解项目的"build.gradle"文件里代码仓库的设置:
repositories {
mavenLocal()
maven{ url "http://SVN:8081/nexus/content/groups/public"}
mavenCentral()
jcenter()
}
深刻理解Gradle里的Task
Task是Gradle最基本最核心的概念!Task可以理解为Gradle的执行单元,实在是太重要了.Gradle通过一个个task来完成具体的构建任务,下面我们来看下Task的定义.
task myTask {
println "config myTask"
}
我们执行下: gradle myTask
输出: config myTask
再执行下: gradle clean
输出: config myTask
可以看出,通过上述方式定义的task,括号内部的代码会在配置阶段执行,也就是说,只要我执行任何一个task,那段代码都会执行,因为每个task执行之前都需要进行一遍完整的配置.
但是很多时候我们并不需要写配置代码,我们想要括号内的代码仅仅在执行我们的task的时候才执行,这个时候可以通过doFirst
或者doLast
来完成.
doFirst:task执行时,最开始的操作
doLast:task执行时,最后的操作
// 定义并配置myTask
task myTask {
println "config myTask"
}
myTask.doLast {
println "after execute myTask"
}
myTask.doFirst {
println "before execute myTask"
}
执行结果如下
config myTask
:app:myTask
before execute myTask
after execute myTask
除此之外,doLast还有一个等价的缩写<<
,因此下面的实现效果等价:
myTask.doLast {
println "after execute myTask"
}
myTask << {
println "after execute myTask"
}
Gradle本身还提供了一些已有的Task供我们使用,比如Copy,Delete,Sync等.因此我们定义Task的时候是可以继承已有的Task,比如我们可以继承自系统的Copy Task来完成文件的拷贝操作.
task myTask(type: Copy) {
...
}
定义Task的时候是可以指定很多参数的,如下所示:
参数 | 含义 | 默认值 |
---|---|---|
name | task的名字 | 不能为空,必须指定 |
type | task的"父类" | DefaultTask |
overwrite | 是否替换已经存在的task | false |
dependsOn | task依赖的task的集合 | [] |
group | task属于哪个组 | null |
description | task的描述 | null |
例如:
task myTask1 << {
println "execute myTask1"
}
task myTask2 << {
println "execute myTask2"
}
// 定义一个名字为rygTask的task,属于renyugang分组,并且依赖myTask1和myTask2两个task.
project.task('rygTask', group: "renyugang", description: "我自己的Task", dependsOn: ["myTask1", "myTask2"] ).doLast {
println "execute rygTask"
}
尝试执行 gradle rygTask
,结果如下:
:app:myTask1
execute myTask1
:app:myTask2
execute myTask2
:app:rygTask
execute rygTask
gradle 发布jar包到nexus
apply plugin: 'maven'
group = 'org.wjw.efjson'
version = "2.8.8"
ext {
buildName = "easyfastjson"
}
uploadArchives {
repositories.mavenDeployer {
def mvnUsername = project.findProperty("mvnUsername") ?: ""
def mvnPassword = project.findProperty("mvnPassword") ?: ""
repository(url: "http://svn:8081/nexus/content/repositories/3rdparty/") {
authentication(userName: mvnUsername, password: mvnPassword)
}
pom.groupId = "${project.group}"
pom.artifactId = "${project.buildName}"
pom.version = "${project.version}"
pom.project {
name project.name
packaging 'jar'
description 'Encapsulates Jackon JSON library, Fast Speed Easy Used Json Lib For java'
licenses {
license {
name 'The Apache Software License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution 'Encapsulates Jackon JSON library, Fast Speed Easy Used Json Lib For java'
}
}
developers {
developer {
id 'wangjunwei'
name 'Wang JunWei'
}
}
}
}
}
//为项目生成**.jar/**-javadoc.jar/**-sources.jar
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from 'doc-api'
}
task sourcesJar(type: Jar) {
classifier = 'sources'
from sourceSets.main.allSource
}
artifacts {
archives jar
archives javadocJar
archives sourcesJar
}
maven项目转化成gradle项目
在maven根目录下运行gradle init --type pom
就会自动生成build.gradle
文件
Gradle Wrapper 引用本地的发布包
Gradle Wrapper 免去了用户在使用 Gradle 进行项目构建时需要安装 Gradle 的繁琐步骤. 每个 Gradle Wrapper 都绑定到一个特定版本的 Gradle,所以当你第一次在给定 Gradle 版本下运行上面的命令之一时,它将下载相应的 Gradle 发布包,并使用它来执行构建.默认,Gradle Wrapper 的发布包是指向的官网的 Web 服务地址,有时候,下载这个发布包比较慢甚至不成功,本文演示了加速下载发布包的方式.
Gradle Wrapper 的配置在gradle/wrapper/gradle-wrapper.properties, 其默认的配置如下:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-bin.zip
其中,distributionUrl
指 明了 Gradle Wrapper 下载 Gradle 发布包的位置.如果遇到下载这个发布包比较慢甚至不成功的时候,可以将该地址引到本地的文件,比如:
...
#distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-bin.zip
distributionUrl=file\:/D:/software/webdev/java/gradle-3.5-all.zip
...
这样构建的速度将会非常快了.当然,前提是,要实现准本好发布包放到本地.
依赖管理
几乎所有基于JVM的项目都会或多或少依赖其他库,假设你在开发一个基于web的项目,你很可能会依赖很受欢迎的开源框架比如Spring MVC来提高效率.Java的第三方库一般以JAR文件的形式存在,一般用库名加版本号来标识.随着开发的进行依赖的第三方库增多小的项目变的越来越大,组织和管理你的JAR文件就很关键.
由于Java语言并没提供依赖管理的工具,所以你需要自己开发一套存储和检索依赖的想法.你可能会采取以下几种常见的方法:
- 手动复制JAR文件到目标机器,这是最原始的很容易出错的方法.
- 使用一个共享的存储介质来存储JAR文件(比如共享的网盘),你可以加载网络硬盘或者通过FTP检索二进制文件.这种方法需要开发者事先建立好与仓库的连接,手动添加新的依赖到仓库中.
- 把依赖的JAR文件同源代码都添加到版本控制系统中.这种方法不需要任何额外的步骤,你的同伴在拷贝仓库的时候就能检索依赖的改变.另一方面,这些JAR文件占用了不必要的空间,当你的项目存在相互之间依赖的时候你需要频繁的check-in的检查源代码是否发生了改变.
Gradle有自己的依赖管理实现,除了支持ant和Maven的特性外,Gradle关心的是性能,可靠性和复用性.
当依赖管理器从仓库中查找依赖时,需要通过属性的结合来定位,最少需要提供一个name.
- group: 这个属性用来标识一个组织,公司或者项目,可以用点号分隔,Hibernate的group是org.hibernate.
- name: name属性唯一的描述了这个依赖,hibernate的核心库名称是hibernate-core.
- version: 一个库可以有很多个版本,通常会包含一个主版本号和次版本号,比如Hibernate核心库3.6.3-Final.
- classifier: 有时候需要另外一个属性来进一步的说明,比如说明运行时的环境,Hibernate核心库没有提供classifier.
你可以使用下面的语法在项目中声明依赖:
dependencies {
configurationName group, name, version
}
你先声明你要给哪个配置添加依赖,
Java插件指定了若干依赖配置项,其描述如下:当项目的源代码被编译时,
- compile 配置项中的依赖是必须的.
- runtime 配置项中包含的依赖在运行时是必须的.
- testCompile 配置项中包含的依赖在编译项目的测试代码时是必须的.
- testRuntime 配置项中包含的依赖在运行测试代码时是必须的.
- archives 配置项中包含项目生成的文件(如Jar文件).
动态版本声明
如果你想使用一个依赖的最新版本,你可以使用latest.integration
,比如声明 Cargo Ant tasks的最新版本,你可以这样写 org.codehaus .cargo:cargo-ant:latest-integration,你也可以用一个+号来动态的声明:
dependencies {
//依赖最新的1.x版本
cargo 'org.codehaus.cargo:cargo-ant:1.+'
}
Gradle 项目中gradle.build文件中的buildScript代码块
在 编写Gradle脚本的时候,在build.gradle文件中经常看到这样的代码:
buildScript {
repositories {
mavenCentral()
}
}
repositories {
mavenCentral()
}
这样子很容易让人奇怪,为什么repositories要声明两次哪?buildscript代码块中的声明与下半部分声明有什么不同?
其实答案非常简单.
buildscript
中的声明是gradle脚本自身需要使用的资源.可以声明的资源包括依赖项,第三方插件,maven仓库地址等.
而在build.gradle
文件中直接声明的依赖项,仓库地址等信息是项目自身需要的资源.
gradle传递参数给Java项目的main函数
build.gradle文件中配置run
任务中定义如下:
run {
if ( project.hasProperty("appArgs") ) {
args Eval.me(appArgs)
}
}
命令行
gradle run -PappArgs="['-u', 'myuser', 'some other argument', 'and/a/path']"
其中我们的参数名为appArgs
,注意-P
为参数的标识,别丢了.
这样我们就将appArgs
代表的参数传递给了main函数.