构建脚本介绍
Gradle构建中的两个基本概念是项目(project)和任务(task),每个构建至少包含一个项目,项目中包含一个或多个任务。
在多项目构建中,一个项目可以依赖于其他项目;类似的,任务可以形成一个依赖关系图来确保他们的执行顺序。
项目-任务关系

上图是一个项目任务关系图。
- Project1依赖Project2
- Project1中,TaskA依赖TaskB和TaskC
- Project2中,TaskF依赖TaskE,TaskE依赖TaskD
项目
一个项目代表一个正在构建的组件(比如一个jar文件),当构建启动后,Gradle会基于build.gradle
实例化一个org.gradle.api.Project
类,并且能够通过project变量使其隐式可用。
group
、name
、version
apply
、dependencies
、repositories
、task
- 属性的其他配置方式:
ext
、gradle.properties
任务
任务对应org.gradle.api.Task
。主要包括任务动作和任务依赖。任务动作定义了一个最小的工作单元。可以依赖于其他任务、动作序列和执行条件。
任务中的方法举例:
- dependsOn
- doFirst、doLast
自定义任务
自动创建test目录结构
1.在build.gradle文件中,添加任务
def createDir = {
path ->
File dir = new File(path)
if(!dir.exists()){
dir.mkdirs()
}
}
task makeJavaDir(){
def paths = ['src/test/java','src/test/resources']
doFirst {
paths.forEach(createDir)
}
}
2.重新导入依赖
不重新导入依赖,可能会看不到自定义任务
3.在Tasks->other
下执行makeJavaDir

自定义创建web目录
1.在build.gradle文件中,添加任务
task makeWebDir(){
dependsOn 'makeJavaDir'//依赖任务makeJavaDir
def paths = ['src/main/webapp','src/test/webapp']
doLast {
paths.forEach(createDir)
}
}
这里第二行我们使用dependsOn方法,依赖我们上一个任务makeJavaDir。这样在创建web目录时,可以把test目录也创建好。
2.重新导入依赖
不重新导入依赖,可能会看不到自定义任务
3.在Tasks->other
下执行makeWebDir

构建的生命周期

理解构建的生命周期,生命周期通常会暴露扩展点,以供开发者使用,影响构建的行为,创建灵活的功能。

初始化
初始化项目,决定有哪些项目参与到构建过程中
配置
生成Task的执行关系和执行图
执行
执行Task的动作
依赖管理
概述
几乎所有的基于JVM的软件项目都需要依赖外部类库来重用现有的功能。自动化的依赖管理可以明确依赖的版本,可以解决因传递性依赖带来的版本冲突。
工件坐标
- group、name、version
常用仓库
- mavenLocal/mavenCentral/jcenter
- 自定义maven仓库
- 文件仓库
依赖的传递性
B依赖A,如果C依赖B,那么C依赖A
自动化依赖管理
首次使用jar,会从远程仓库下载到本地仓库;
如果多次使用相同的jar,会缓存到本地缓存
依赖阶段配置
- compile、runtime
- testCompile、testRuntime
依赖阶段关系
添加logback编译时依赖
compile 'ch.qos.logback:logback-classic:1.2.1'
解决版本冲突
版本冲突例子

解决冲突
- 查看依赖报告

- 排除传递性依赖
- 强制指定一个版本
注意:gradle会默认解决版本冲突,使用最高版本的冲突依赖。
- 修改默认解决策略
configuration.all{
resolutionStrategy{
failOnVersionConflict()
}
}
让版本冲突出现时报错,让我们知道。
排除传递性依赖
compile('org.hibernate:hibernate-core:3.6.3.final'){
exclude group:"org.slf4j",module:"slf4j-api"
//transitive = false
}
其中module,就是name。
强制指定一个版本
configuration.all{
resolutionStrategy{
force 'org.slf4j:slf4j-api:1.7.24'
}
}
多项目构建介绍
项目模块化
在企业项目中,包层次和类关系比较复杂,把代码拆分成模块通常是最佳实践,这需要你清晰的划分功能的边界,比如把业务逻辑和数据持久化拆分开来。项目符合高内聚低耦合时,模块化就变得很容易,这是一条非常好的软件开发实践。
TODO模块依赖关系

配置要求
- 所有项目应用Java插件
- web子项目打包成war
- 所有项目添加logback日志功能
- 统一配置公共属性
项目拆分,gradle多项目构建
1.新建两个模块,都是gradle项目
1.1 右键点击根目录todo,new->Module

1.2 新建gradle模块,点击next

1.3 填入模块名,然后next,再next

1.4 按照上面三步建立model
、repository
和web
模块
1.5 根目录下的setting.gradle
文件中会有gradle管理的项目描述
rootProject.name = 'todo'
include 'model'
include 'repository'
include 'web'
1.6添加模块依赖
我们的项目repository模块依赖model模块,web模块依赖repository模块。
所以需要在repository模块中添加model模块的依赖,在web模块中添加repository模块依赖。
dependencies {
compile project(":model")
testCompile group: 'junit', name: 'junit', version: '4.12'
}
dependencies {
compile project(":repository")
testCompile group: 'junit', name: 'junit', version: '4.12'
}
多项目构建实战
1.所有项目中应用Java插件
将子模块的java插件配置都删除,在根项目中使用allprojects方法应用
group 'com.kim.gradle'
version '1.0-SNAPSHOT'
allprojects {
apply plugin:'java'
sourceCompatibility = 1.8
}
repositories {
mavenCentral()
}
//省略其他配置
2.web子项目打包成war
个性化需求,给web子模块应用war插件

3.所有项目添加logback日志功能,包括Junit
allprojects {
apply plugin:'java'
sourceCompatibility = 1.8
}
subprojects {
repositories {
mavenCentral()
}
dependencies {
compile 'ch.qos.logback:logback-classic:1.2.1'
testCompile 'junit:junit:4.12'
}
}
这里用subprojects可以达到同样的效果
4.统一配置group和version
在根目录下新建gradle.properties
文件,加入这两个属性。
group=com.kim.gradle
version=1.0-SNAPSHOT
同时,子模块中删除这两个属性。
5.执行root项目的clean任务
执行root项目的clean任务,观察执行顺序。
> Task :clean
> Task :model:clean UP-TO-DATE
> Task :repository:clean UP-TO-DATE
> Task :web:clean
自动化测试
1.测试配置
dependencies {
testCompile 'junit:junit:4.12'
}
2.测试发现
gradle是如何发现哪些类或方法是测试类的呢
- 任何继承自junit.framework.TestCase或groovy.util.GroovyTestCase的类
- 任何被@RunWith注解的类
- 任何至少包含一个被@Test注解的类
发布
配置发布插件
allprojects {
apply plugin:'java'
sourceCompatibility = 1.8
apply plugin: 'maven-publish'
publishing {
publications {
myPublish(MavenPublication){
from components.java
}
}
repositories {
maven {
name "myRepo"
url ""
}
}
}
}
发布到本地仓库

发布到公司私服
在发布插件配置中配置公司私服的url,然后执行publish这个任务

Time waits for no one.