三种构建工具的比较 ant和maven基于xml,格式过于固定,不灵活tomcat源码是用ant编译的gradle不依赖xml,可以使用groovy脚本来构建,更灵活,可以直接用脚本,且兼容ant和maven
安装配置 需要jdk8及以上
BASH
1 2 3 4 5 6 7 8 9 10 11 12 13 mkdir ~/software && cd ~/softwarewget https://downloads.gradle-dn.com/distributions/gradle-7.4.1-all.zip unzip gradle-7.4.1-all.zip rm -rf gradle-7.4.1-all.zipecho " GRADLE_HOME=/home/easul/software/gradle-7.4.1 PATH=\$GRADLE_HOME\bin:\$PATH export PATH " >> ~/.bash_profilesource ~/.bash_profile
构建脚本编写 构建由一个一个任务构成,这里创建build.gradle来编写脚本,语言使用groovygroovy,scala都是基于java的语言,所以底层都是编译成class运行,而且用java写也是可以的
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 task first { doLast { println "hello" } } task second { doLast { String test = "asdf" System.out.println(test.toUpperCase()) } } task third { doLast { 4. times { println("$it" ) } } }
然后运行任务
这里的doLast是最后执行该任务,如下
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 task first { doLast { 4. times { println("$it + asdf" ) } } } task second { 4. times { println("$it" ) } }
build的三个阶段
Initialization: Gradle决定哪些工程参与构建(可有多个工程),每个工程建一个Project实例。工程信息在settings.gradle中定义
Configuration:配置Project实例,所有工程的构建脚本都会执行,Task, Configuration和许多其他的对象都会被创建和配置
Execution:gradle通过构建好的task名称执行任务
doLast的任务在Execution阶段执行,剩下的都在Configuration阶段执行 后边的阶段执行了,前边的阶段就会执行
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 println("1" ) task first { println("2" ) } task second { println("3" ) doLast { println("4" ) } }
任务构建 普通任务
GROOVY
1 2 3 4 5 6 7 8 task test task test2 { doLast { println("Father" ) } }
任务依赖
在声明任务时就声明依赖
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 task first { doLast { println("first" ) } } task second(dependsOn: first) { doLast { println("second" ) } }
在声明完任务后再声明依赖
GROOVY
1 2 3 4 5 6 7 8 9 10 11 task test { doLast { println("Son" ) } } task test2 { doLast { println("Father" ) } } test.dependsOn test2
闭包中声明依赖
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 task first { doLast { println "first" } } first.dependsOn { tasks.findAll { task -> task.name.startsWith('lib' ) } } task lib1 { doLast { println "lib1" } } task lib2 { doLast { println "lib2" } } task wlib2 { doLast { println "wlib2" } }
定位任务
GROOVY
1 2 3 4 5 6 task first println first.name println project.first.name
将任务看成数组
GROOVY
1 2 3 4 5 6 7 task first task second println tasks.first.name println tasks["second" ].name
在任务中添加描述 主要是用于方便任务阅读
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 task copy(type: Copy) { description 'Copies the resource directory to the target directory' from 'resources' into 'target' include('**/*.txt' , "**/*.xml" , "**/*.properties" ) println("description applied" ) }
跳过任务
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 task compile { doLast { println("compile" ) } } compile.doFirst { if (true ) { throw new StopExecutionException() } } task first(dependsOn: 'compile' ) { doLast { println("first" ) } }
依赖管理 声明依赖关系 也就是jar包的依赖,在dependencies写入
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 apply plugin: 'java' repositories { mavenLocal() maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' } maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' } mavenCentral() } dependencies { implementation group: 'com.alibaba' , name: 'fastjson' , version: '1.2.79' }
依赖关系配置
编译
运行时:默认包含编译阶段
测试编译:默认包含编译产生的类和编译时的依赖
测试运行时:默认包含运行时和测试的依赖
发布文件 可以将包文件发布到远程库
GROOVY
1 2 3 4 5 6 7 8 9 10 apply plugin 'maven' uploadArchives { repositories { mavenDeployer { repository(url: "file://localhost/tmp/myRepo/" ) } } }
gradle插件 用于编译,设置域对象,设置源文件,测试,打包等等
插件类型
脚本插件:额外的构建脚本,通常在构建中使用
二进制插件(对象插件):实现插件接口并用编程的方法来操作构建的类。
应用插件 使用Project.apply()方法
脚本插件 新建other.gradle,写入如下内容
GROOVY
1 2 3 4 5 ext { theVersion='1.0' url='http://212490197.xyz' }
在build.gradle应用脚本插件
GROOVY
1 2 3 4 5 6 7 8 9 apply from: 'other.gradle' task first { doLast { println("version: $theVersion" ) println("url: $url" ) } }
二进制插件 二进制插件就是实现了org.gradle.api.Plugin接口
内部插件 是gradle自己实现的插件,可以使用如下方法引入
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 apply plugin: JavaPlugin plugin { id: 'java' } plugins { id "jp.co.soramitsu.sora-plugin" version "0.5.0" } buildscript { repositories { maven { url "https://plugins.gradle.org/m2/" } } dependencies { classpath "jp.co.soramitsu:sora-plugin:0.5.0" } } apply plugin: "jp.co.soramitsu.sora-plugin"
编写自定义插件 实现org.gradle.api.Plugin即可
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 apply plugin: HelloPlugin class HelloPlugin implements Plugin <Project> { void apply(Project project) { project.task('hello' ) { doLast { println("doLast" ) } } } }
自定义插件扩展
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class HelloPlugin implements Plugin <Project> { void apply(Project project) { project.extensions.create('greeting' , HelloPluginExtension) project.task('hello' ) { doLast { println(project.greeting.message) } } } } class HelloPluginExtension { String message } apply plugin: HelloPlugin greeting.message = "extension plugin" greeting { message = "extension plugin" }
标准gradle插件
插件id
自动应用
描述
java
java-base
向项目添加java编译,测试和绑定的功能,是许多gradle插件的基础
groovy
java,groovy-base
添加对groovy项目的支持
scala
java,scala-base
添加对scala项目的支持
antlr
java
添加对Antlr生成解析器的支持
source sets(源集) 源集就是用于编译执行的源文件集合,包含源代码和资源文件(如java文件下的main和test) 源集有相应的编译类路径和运行时类路径 源集相关属性
属性
类型
默认值
描述
name-只读
String
非空
源集名字
output-只读
SourceSetOutput
非空
源集输出文件,包括编译过的类和资源
output.classesDirs-只读
FileCollection
$buildDir/classes/java/$name 如build/classes/java/main
源集编译过的class文件目录
output.resourcesDir-只读
File
$buildDir/resources/$name 如build/resources/main
源集产生的资源目录
java-只读
SourceSetOutput
${project.projectDir}/src/ ${sourceSet.name}/java/
源集的java源代码,只包含.java,会排除其他类型
java.srcDirs
Set
src/$name/java,如src/main/java
源集的java源文件的源目录,是一个集合,可以设置多个源代码目录,更改源代码目录就是更改这个属性
java.outputDirs
File
$buildDir/classes/java/$name 如build/classes/java/main/
源代码编译的class文件输出目录
resources-只读
SourceSetOutput
${project.projectDir}/src/ ${sourceSet.name}/resources/
源集的资源,只包含资源
resources.srcDirs
Set
src/$name/resources,如src/main/resources
源集的资源目录,是一个集合,可以指定多个
sourceSets DSL sourceSets API
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 sourceSets { other2 { output.resourcesDir = file('out/bin' ) java.outputDir = file('out/bin' ) java { srcDirs = ['src/other2/other3/java' ] } resources { srcDirs = ['src/other2/other3/resources' ] } } } task outSourceSet { doLast { sourceSets.all { println("$name" ) } println ("${sourceSets.main.name}" ) println ("${sourceSets.other2.name}" ) println ("${sourceSets.test.name}" ) println ("${sourceSets.main.java.srcDirs}" ) println ("${sourceSets.main.resources.srcDirs}" ) println ("${sourceSets.other2.java.srcDirs}" ) println ("${sourceSets.other2.resources.srcDirs}" ) } }
为源集添加依赖
GROOVY
1 2 3 4 5 6 7 8 9 dependencies { implementation group: 'com.alibaba' , name: 'fastjson' , version: '1.2.79' testImplementation group: 'com.alibaba' , name: 'fastjson' , version: '1.2.79' other2Implementation group: 'com.alibaba' , name: 'fastjson' , version: '1.2.79' }
将源集打jar包
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 task otherJar(type: Jar) { archiveBaseName = sourceSets.other2.name archiveVersion = '0.1.0' destinationDirectory = file("${project.projectDir}/jar" ) from sourceSets.other2.output } tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } jar { mainfest { attributes "Manifest-Version" : 1.0 , "Main-Class" : "ml.lightly.demo.Test" } }
为源集生成doc
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 task otherDoc(type: Javadoc) { destinationDir = file("${project.projectDir}/doc" ) source sourceSets.other2.allJava title sourceSets.other2.name } tasks.withType(Javadoc) { options.encoding = 'UTF-8' }
groovy编码失败
GROOVY
1 2 3 4 tasks.withType(GroovyCompile) { groovyOptions.encoding = 'MacRoman' }
其他常用属性解释
GROOVY
1 2 3 4 5 6 7 8 9 10 group = 'ml.lightly.demo' archivesBaseName="hello" version = '0.0.1-SNAPSHOT' sourceCompatibility = '8' targetCompatibility = '8'
gradle运行构建 执行多个任务 依赖多个任务用[]
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 task task1 { doLast { println("1" ) } } task task2(dependsOn: task1) { doLast { println("2" ) } } task task3(dependsOn: [task1, task2]) { doLast { println("3" ) } } task task4(dependsOn: [task1, task3]) { doLast { println("4" ) } }
排除任务
BASH
1 2 3 4 gradle task4 -x task3
查看任务流程
选择执行哪些构建 默认找的是当前目录下的xx.gradle文件 通过-b参数指定运行其他目录的构建的任务
BASH
1 gradle -q -b otherdir/test.gradle hello
文件结构
1 2 3 ├── build.gradle └── otherdir └── test.gradle
test.gradle内容
GROOVY
1 2 3 4 5 6 task hello { doLast { println "${buildFile.name}, ${buildFile.parentFile.name}" } }
获取构建信息
列出任务
其他常用命令
BASH
1 2 3 4 5 6 7 8 9 10 gradle -q help -task gradle -q dependencies gradle -q api:dependencies --configuration gradle -q dependencyInsight gradle -q properties
gradle构建java项目
目录结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ├── gradle │ └── wrapper │ ├── gradle-wrapper.java gradle的wrapper │ └── gradle-wrapper.properties 可以修改里边的distributionUrl为本地路径 ├── app 自己创建的名为app的模块 │ ├── build.gradle │ └── src │ ├── main │ │ ├── java │ │ └── resources │ └── test │ ├── java │ └── resources ├── gradlew gradle的执行脚本 └── settings.gradle
命令行构建
BASH
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 gradle init Select type of project to generate: 1: basic 2: application 3: library 4: Gradle plugin Enter selection (default: basic) [1..4] 2 Select implementation language: 1: C++ 2: Groovy 3: Java 4: Kotlin 5: Scala 6: Swift Enter selection (default: Java) [1..6] 3 Select build script DSL: 1: Groovy 2: Kotlin Enter selection (default: Groovy) [1..2] 1 Select test framework: 1: JUnit 4 2: TestNG 3: Spock 4: JUnit Jupiter Enter selection (default: JUnit 4) [1..4] Project name (default: demo): Source package (default: demo): BUILD SUCCESSFUL 2 actionable tasks: 2 executed
build.gradle内容
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 apply plugin: 'java' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' group = 'ml.lightly.demo' version = '0.0.1-SNAPSHOT' repositories { mavenLocal() mavenCentral() } buildscript { ext { springBootVersion = ‘2.3 .2 .RELEASE’ } repositories { mavenLocal() maven { url 'https://maven.aliyun.com/nexus/content/groups/public' } maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' } maven { url 'https://repo.spring.io/plugins-release' } mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" ) } } sourceSets { main { java { srcDir 'src' } } test { java { srcDir 'test' } } } dependencies { compile "org.springframework.boot:spring-boot-starter-web" implementation group: 'com.alibaba' , name: 'fastjson' , version: '1.2.79' compile project(":module-name" ) } tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } sourceCompatibility = '8' targetCompatibility = '8' jar { mainfest { attributes "Manifest-Version" : 1.0 , "Main-Class" : "ml.lightly.demo.Test" } }
settings.gradle内容
GROOVY
1 2 3 4 rootProject.name = 'gradle' include('app' )
编译jar包
gradle构建groovy项目 构建出来后的build.gradle内容
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 apply plugin: 'groovy' repositories { mavenLocal() mavenCentral() } dependencies { compile 'org.codehaus.groovy:groovy-all:2.4.5' }
gradle测试 可以使用JUnit或JUnit Jupiter(后者更好)
跳过测试用例
GROOVY
1 2 3 test { enabled = false }
指定测试用例可被测试
GROOVY
1 2 3 4 test { include("ml/lightly/demo/gradle/*" ) }
排除测试用例让其不被测试
GROOVY
1 2 3 4 test { exclude("ml/lightly/demo/gradle/*" ) }
gradle多项目构建 例如微服务中,service,entry,dao各自都是一个模块,就需要多模块构建 一个项目(project)有多个模块(module)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ├── gradle │ └── wrapper │ ├── gradle-wrapper.java gradle的wrapper │ └── gradle-wrapper.properties 可以修改里边的distributionUrl为本地路径 ├── app 自己创建的名为app的模块 │ ├── build.gradle │ └── src │ ├── main │ │ ├── java │ │ └── resources │ └── test │ ├── java │ └── resources ├── sercive 自己创建的service模块 │ ├── build.gradle │ └── src │ ├── main │ │ ├── java │ │ └── resources │ └── test │ ├── java │ └── resources ├── gradlew gradle的执行脚本 ├── build.gradle └── settings.gradle
默认创建了app模块,可以自己复制这个文件夹,然后改名添加一个新的模块,如servicesettings.gradle再添加include('service') 每个模块可以在xx.gradle加上description 最外层也可以添加一个build.gradle,用于指定所有子模块的的配置
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 description "root project" allprojects { group 'ml.lightly.demo' version '0.0.1-SNAPSHOT' repositories { mavenLocal() maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' } maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' } } task hello { doLast { task -> println("${task.project.name}" ) } } } subprojects { apply plugin: 'java' hello { doLast { task -> println("subproject + ${task.project.name}" ) } } } project(':service' ).hello { doLast { task -> println("service + ${task.project.name}" ) } }
子工程各自的依赖包可以自行配置,不需要在顶层统一配置
settings.gradle配置
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 rootProject.name = 'gradle' rootProject.children.each {project -> project.buildFileName = "${project.name}.gradle" } include('app' ) include('service' )
Gradle部署 使用maven插件发布 在子模块,如service,添加如下发布命令
GROOVY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 apply plugin: 'maven-publish' publishing { publications { maven(MavenPublication) { from(components.java) } } repositories { maven { url "$buildDir/repo" } } }
在命令行执行
BASH
1 2 3 4 5 6 gradle build -q -b service/build.gradle gradle publish -q -b service/build.gradle
将项目从Maven转换为Gradle 直接转换pom.xml即可
BASH
1 2 3 gradle init --type pom
其他
GROOVY
1 2 3 4 5 rootProject.name = 'gradle' rootProject { name = 'gradle' }
讲解视频