构建脚本介绍

Gradle构建中的两个基本概念是项目(project)和任务(task),每个构建至少包含一个项目,项目中包含一个或多个任务。

在多项目构建中,一个项目可以依赖于其他项目;类似的,任务可以形成一个依赖关系图来确保他们的执行顺序。

项目-任务关系

上图是一个项目任务关系图。

  1. Project1依赖Project2
  2. Project1中,TaskA依赖TaskB和TaskC
  3. Project2中,TaskF依赖TaskE,TaskE依赖TaskD

项目

一个项目代表一个正在构建的组件(比如一个jar文件),当构建启动后,Gradle会基于build.gradle实例化一个org.gradle.api.Project类,并且能够通过project变量使其隐式可用。

  • groupnameversion
  • applydependenciesrepositoriestask
  • 属性的其他配置方式:extgradle.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 按照上面三步建立modelrepositoryweb模块
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.