1.使用
在build.gradle中添加以下语句,表示插入java插件
apply plugin:'java'
2.source sets
java插件引入了sourceset这个概念,sourceset将编译时和执行时所要用到的source文件组合在一起,其中包含java的源文件和资源文件,有的插件还包括了groovy和Scala资源文件,sourceset与编译环境和运行环境都存在联系。
使用sourceset的目的是将一些源文件组合起来,为了某个特殊的目的在逻辑上进行分组。例如,你可能把测试的集合单独拿出来组合成一个sourceset,或者一些API啊,你项目中的实现类啊等等,都可以定义为一个sourceset。这只是个概念的问题,你知道知道你分组的意义:方便你管理文件。
java中定义了2个sourceset:一个是main group,还有一个是test group。
main:项目中的源文件,编译后组装到jar包中的。
test:项目的测试源码,例如JUint和TestNG写的测试代码。
3.任务
java plugin任务
compileJava:目的是编译java源文件,利用javac。依赖compile任务,属于JavaCompile类型。
-
apply plugin: 'java'
-
compileJava {
-
//enable compilation in a separate daemon process
-
options.fork = true
-
-
//enable incremental compilation
-
options.incremental = true
-
}
processResource:将项目的资源文件复制到项目class目录中。无依赖。属于Copy类型,严格来说是Copy的子类。
classes :组装class目录。依赖compileJava和processResource两个任务,还有一些编译的任务 。属于Task类型。
compileTestJava:编译测试源码,利用javac。依赖compile和一些产生测试编译环境的任务。属于JavaCompile类型。
processTestResource:将测试资源文件复制到项目class文件目录中。无依赖。属于Copy类型。
testClasses:组合测试的class目录。依赖compileTestJava和processTestResource和一些添加测试的编译任务。属于Task类型。
jar:组合成jar文件,依赖compile。属于Jar类型。
javadoc:生成java帮助文档,依赖compile。属于Javadoc类型。
test:执行测试case,依赖compile,compileTest等。属于Test类型
uploadArchives:上传存档文件。依赖那些在archives配置中产生镜像的任务,比如jar。属于UpLoad类型。
clean:删除build文件,使项目回归最原始状态.属于Delete类型。
cleanTaskName:删除由任务产生的文件,比如cleanJar就是删除有任务jar产生的文件,cleanTest就是删除由test产生的文件。属于Delete类型。
专门处理sourceset的任务
compile
:利用javac编译sourceset定义的源文件,依赖所有产生sourceset编译类路径的任务。属于JavaCompile类型SourceSet
Java
process
:将sourceset定义的资源文件复制到class目录中,无依赖,属于Copy类型。SourceSet
Resources
:组合sourceset中定义的文件目录,依赖compileSourceSetJava和processSourceSetResources两个任务,属于Task类型。sourceSet
Classes
生命周期类任务
assemble:组合分析所有的档案文件。依赖所有的存档文件。属于Task类型。
check:执行所有的验证类任务,依赖所有验证类任务,包括test。属于Task类型。
build:执行构建,依赖check和assemble,属于Task类型。
buildNeeded:执行构建,依赖testCompile配置的子项目中build和buildNeeded任务,属于Task类型。
buildDependents:执行构建,依赖当前项目的子项目的build和buildDependents任务。属于Task类型。
buildConfigName:为特殊的配置类任务构建一个镜像,该任务都是隐式添加的。依赖configName代表的任务。属于Task类型。
uploadConfigName:为某一个配置任务分配镜像,然后上传镜像,该任务都是隐式添加的。依赖configName定义的任务,属于UpLoad类型。
任务依赖关系图
4.项目布局
java plugin规定一些项目目录的结构,但是下面的目录并不是要求必须存在。java在编译的时候,会访问下面所有的目录,如果不存在,会记住这些没有的目录。
src/main/java:java源文件
src/main/resources:项目资源文件
src/test/java:测试源文件
src/test/resources:测试资源文件
src/sourceSet/java:sourceset定义的java源文件,注意其中的sourceSet一级是根据sourceSet定义的目录名替换的。下同
src/sourceSet/resourcs:sourceset定义的资源文件
修改上面默认的目录
通过下面的方式可以修改默认的目录结构,定义你自己想要的目录
-
sourceSets{
-
main{
-
java{
-
srcDir 'src/java'
-
}
-
resources{
-
srcDir 'src/resources'
-
}
-
}
-
}
这是sourceSets很重要的应用。
5.依赖管理
上面的图是从文档上截取下来的,它列举了任务之间的依赖关系,比如第一个compile是被compileJava所依赖的,即执行compile前,会先执行compile。所以要理解Name列是被依赖的任务,一般是全局任务,不是java插件特有的,而Used by tasks一般是plugin特有的。Extends则说明继承的任务,说明该任务是在被继承任务的基础上扩展的。
再来看另外一张图:
上面的图更加的清晰展现出java任务和gradle任务之间的联系,浅蓝色的代表java任务,绿色代表gradle任务。用used by标注的代表箭头指向的任务使用了左边的任务。
而uploadArchives和archives之前的关系是uploads,说明uploadArchives依赖于archives任务,等archives任务生成存档文件后,uploadArchives就会把这些存档文件上传。
而jar 和archives、runtime之间的关系是,在后者执行的时候,jar任务会将定义的jar包添加其中。那么这个依赖关系到底怎么算,是说jar任务依赖runtime,还是runtime依赖jar呢,应该是jar依赖runtime。因为runtime其实不管你有没有jar任务,如果有才会将jar任务定义的东西执行,如果没有,也是不会影响它。但是jar任务就不同了,没有runtime,jar还有用么?
下面再来看看谁能sourceSet任务的依赖配置,于java plugin正常任务的图是一样的,就不多解释了。
6.常用属性
目录属性
目录属性都是成双成对出现,目录名+目录。目录名是一个文件夹的名称,相对于build目录,而目录则是加上build目录。一些默认值上面都列举出来,不想浪费时间一一列举了。
其他属性
比较重要的是sourceSets,包含了项目中定义的sourcesets,下面一节会详细介绍。archivesBaseName项目压缩包的名称。manifest操作MANIFEST文件的。
7.操作source set
(终于到了能写点代码的时候了)
获取sourceset属性
-
apply plugin: 'java'
-
println sourceSets.main.output.classesDir
-
println sourceSets[ 'main'].output.classesDir
-
sourceSets{
-
println main.output.classesDir
-
}
-
sourceSets{
-
main{
-
println output.classesDir
-
}
-
}
-
-
sourceSets.all{
-
println name
-
}
执行gradle命令后输出:
-
D:\GRADLE~ 2\ 0112>gradle -q
-
D:\gradle_product\ 0112\build\classes\main
-
D:\gradle_product\ 0112\build\classes\main
-
D:\gradle_product\ 0112\build\classes\main
-
D:\gradle_product\ 0112\build\classes\main
-
main
-
test
-
-
Welcome to Gradle 2.2.1.
-
-
To run a build, run gradle <task> ...
-
-
To see a list of available tasks, run gradle tasks
-
-
To see a list of command-line options, run gradle --help
说明想要获得sourcesets中属性值的方法有很多种,上面的程序中就列举了4种。
配置sourceset属性
-
apply plugin: 'java'
-
-
sourceSets{
-
main{
-
java{
-
srcDir 'src/java'
-
}
-
resources{
-
srcDir 'src/resources'
-
}
-
}
-
-
}
-
println sourceSets.main.java.srcDirs
-
println sourceSets[ 'main'].resources.srcDirs
-
sourceSets{
-
println main.java.srcDirs
-
}
-
sourceSets{
-
main{
-
println java.srcDirs
-
}
-
}
-
-
sourceSets.all{
-
println name
-
}
根据实际操作来看,我们只是添加了一个java目录和一个resources目录。
-
D:\GRADLE~ 2\ 0112>gradle -q
-
[D:\gradle_product\ 0112\src\main\java, D:\gradle_product\ 0112\src\java]
-
[D:\gradle_product\ 0112\src\main\resources, D:\gradle_product\ 0112\src\resources
-
]
-
[D:\gradle_product\ 0112\src\main\java, D:\gradle_product\ 0112\src\java]
-
[D:\gradle_product\ 0112\src\main\java, D:\gradle_product\ 0112\src\java]
-
main
-
test
-
-
Welcome to Gradle 2.2.1.
-
-
To run a build, run gradle <task> ...
-
-
To see a list of available tasks, run gradle tasks
-
-
To see a list of command-line options, run gradle --help
设置sourcesets属性
上面的表格列举了一些sourceset重要的属性,其中的一些属性在之前的2个例子中也有涉及。
定义新的sourceset属性
-
apply plugin: 'java'
-
-
sourceSets{
-
intTest
-
}
-
-
dependencies {
-
intTestCompile 'junit:junit:4.11'
-
intTestRuntime 'org.ow2.asm:asm-all:4.0'
-
}
在上面的代码中,我们定义了一个新的属性,叫做intTest,然后定义了2个依赖任务intTestCompile和intTestRunTime。这个我们在第5节.依赖管理中讲过,sourceset的依赖管理中可以根据属性值设置任务,刚好可以回过头复习复习。执行下任务:
-
D:\GRADLE~ 2\ 0112>gradle intTestClasses
-
:compileIntTestJava UP-TO-DATE
-
:processIntTestResources UP-TO-DATE
-
:intTestClasses UP-TO-DATE
-
-
BUILD SUCCESSFUL
-
-
Total time: 2.699 secs
sourceset相关样例
-
apply plugin: 'java'
-
-
sourceSets{
-
intTest
-
}
-
-
dependencies {
-
intTestCompile 'junit:junit:4.11'
-
intTestRuntime 'org.ow2.asm:asm-all:4.0'
-
}
-
//将intTest输出文件打成jar包
-
task intTestJar(type:Jar){
-
from sourceSets.intTest.output
-
}
-
//为intTest中所有的java文件生成java帮助文档
-
task intTestJavadoc(type:Javadoc){
-
source sourceSets.intTest.allJava
-
}
-
//为intTest添加测试
-
task intTest(type:Test){
-
testClassesDir = sourceSets.intTest.output.classesDir
-
classpath = sourceSets.intTest.runtimeClasspath
-
}
首先我们执行intTest任务:
-
D:\GRADLE~ 2\ 0112>gradle intTestJar
-
:compileIntTestJava UP-TO-DATE
-
:processIntTestResources UP-TO-DATE
-
:intTestClasses UP-TO-DATE
-
:intTestJar
-
-
BUILD SUCCESSFUL
-
-
Total time: 4.337 secs
会在build/libs目录下生成jar包
然后我们执行intTestJavadoc来生成java帮助文档:
-
D:\GRADLE~ 2\ 0112>gradle intTestJavadoc
-
:intTestJavadoc UP-TO-DATE
-
-
BUILD SUCCESSFUL
-
-
Total time: 2.73 secs
执行成功,但是不会生成javadoc,因为我没有定义intTest具体细节
最后来执行测试
-
D:\GRADLE~ 2\ 0112>gradle intTest
-
:compileIntTestJava UP-TO-DATE
-
:processIntTestResources UP-TO-DATE
-
:intTestClasses UP-TO-DATE
-
:intTest UP-TO-DATE
-
-
BUILD SUCCESSFUL
-
-
Total time: 2.793 secs
8.Javadoc
任务javadoc是Javadoc类的一个实例,支持核心java文档选项和标准doclet格式,为了完整的继承这些特性,gradle定义了2个类:CoreJavadocOptions和StandardJavadocDocletOptions。详细信息也可以去这两个类中去查查。
javadoc中的一些属性:
classpath:执行环境,sourceSets.main.output代表的目录,以及sourceSets.main.compileClasspath代表的目录。是FileCollection的
source:源码文件目录,sourceSets.main.allJava代表的目录,是FileTree类型的。
destinationDir:生成的文档存放目录
title:项目的版本和名称
9.clean
该任务是Delete的一个实例,删除用dir描述的目录
10.Resources
是sourceset中的属性,一般是通过Copy处理资源相关信息。会被ProcessResources用到:
ProcessResources.srcDirs引用的是sourceSet.resources的值。
ProcessResources.destinationDir引用的是sourceSet.output.resourcesDir的值。
11.CompileJava
java plugin为项目中的每一个sourceset都提供一个CompileJava对象实例。在脚本中是下面的样式
-
apply plugin: 'java'
-
compileJava {
-
//enable compilation in a separate daemon process
-
options.fork = true
-
-
//enable incremental compilation
-
options.incremental = true
-
}
classpath:FileCollction,默认值是sourceSet.compileClasspath
source:FileTree,默认值是sourceSet.java
destinationDir:File.默认值是sourceSet.output.classesDir
12.增量式的java编译
该功能正在孵化中,以后有可能更改。
该功能的主要目的是
1.避免在编译了并不需要编译的源文件,提高编译的速度。
2.可能只是改变一点的输出,并不需要重新编译一些没有任何改变的目录。这一点对JRebel很有用。
这个功能肯定是一个高级且难以理解的东西,因为它涉及到底层的算法。所以我想我是不可能弄明白的了,且对我有啥用。只是知道有这么个东西就行。
13.Test
test任务是一个Test实例,它会自动识别和执行source set定义test目录下所有的单元测试,而且会生成测试报告(这个好像挺爽的啊,看来测试驱动开发看能能很容易的实现啦)。
支持JUnit和TestNG。
测试执行
测试的执行是独立于JVM的,和构建的主进程也是分离的,其中关于jvm和运行时状态属性是可以通过API进行修改的。
1.你可以指定是否平行的执行测试。
2.你可以指定执行一定数量的case后重启执行进程。
3.设置case失败后的行为。
4.设置测试输出的log的等级。
调试
可以通过Test.getDebug属性来让jvm进入5005端口,进入调试模式。而且你可以通过命令行模式参数--debug -jvm进入debug模式。
测试过滤
从gradle1.0开始,就具备了执行某些特殊的case,或者根据匹配模式删选case来执行。可以做到以下几点过滤:
1.依据测试方法的等级过滤,执行一个单一的测试。
2.依据自定义的注解(以后实现)
3.依据测试的层次,执行继承某一个基础类的测试(以后实现)
4.依据一些运行时的规则,例如一些特殊的系统属性值或静态状态(以后实现)
说了这么多废话,如果在脚本中定义过滤条件呢?
-
test {
-
filter{
-
//方法名
-
includeTestsMatching "*UiCheck"
-
//包名过滤
-
includeTestsMatching "org.gradle.internal.*"
-
//整合的case
-
includeTestsMatching "*IntegTest"
-
}
-
}
也可以通过gradle命令行的参数来过滤:
根据系统属性来执行单一测试
测试检测
gradle可以自动识别出哪些class是测试类,如果做到的呢,在编译阶段,gradle观察这些编译的java类。而扫描哪些文件夹里的类,你可以去设置,包括哪些文件,不包括哪些文件,都可以自定义。而且它也会扫描出用JUnit和TestNG框架写的case。以JUnit为例来看看。
当使用JUnit的时候,我们会扫描junit3和junit4写的case。
1.类或超类继承与TestCase或者GroovyTestCase。
2.类或超类使用了@RunWith。
3.类或超类包含@Test注解的方法。
当使用TestNG的话,我们只扫描@Test注解的方法。
测试分组
junit分组
-
test{
-
useJUnit{
-
includeCategories 'org.gradle.junit.CategoryA'
-
includeCategories 'org.gradle.junit.CategoryB'
-
}
-
}
TestNG分组
-
test{
-
useJUnit{
-
includeCategories 'org.gradle.junit.CategoryA'
-
includeCategories 'org.gradle.junit.CategoryB'
-
}
-
useTestNG{
-
excludeGroups 'integrationTests'
-
includeGroups 'unitTests'
-
}
-
}
测试报告
gradle默认情况下生成下面3种报告:
1.HTML格式
2.XML格式
3.二进制
可以使用任务testReports来生成测试报告:
-
subprojects{
-
apply plugin: 'java'
-
test{
-
reports.html.enabled = false
-
}
-
}
-
-
task testReport(type:TestReport){
-
destinationDir = file( "$buildDir/report/allTest")
-
reportOn subprojects*.test
-
}
14.Jar任务
jar任务会将项目的源文件和资源文件打成jar包。
jar中manifest属性,定义了jar包的版本和名称。文件位于tmp/<sourceset>/下: