gradle学习(20)-详解java插件

版权声明:本文为Doctorq原创文章,未经博主允许不得转载。 https://blog.csdn.net/qhshiniba/article/details/42672271

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的任务


compileSourceSetJava:利用javac编译sourceset定义的源文件,依赖所有产生sourceset编译类路径的任务。属于JavaCompile类型


processSourceSetResources:将sourceset定义的资源文件复制到class目录中,无依赖,属于Copy类型。


sourceSetClasses:组合sourceset中定义的文件目录,依赖compileSourceSetJava和processSourceSetResources两个任务,属于Task类型。


生命周期类任务


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>/下:





没有更多推荐了,返回首页