构建工具的作用
- 构建管理
- 自动化、测试、打包、发布
主流构建工具
ant、maven、gradle
Groovy
是基于 Java 虚拟机的一种敏捷的动态语言,是一种成熟的面向对象语言。即可以用于面向对象编程,又可以用于纯粹的脚本语言。同时又具有闭包和动态语言的其他特性。
特性:
- 完全兼容 Java 语法
- 分号可选
- 类和方法默认是public
- 编译器自动给属性添加 setter 和 getter 方法
- 属性可直接用点号获取
- 最后一个表达式的值会被作为返回值
- == 号等同于 equals 、无空指针
- 任何地方可以执行 assert (断言)
Groovy-高效特性
1.可选的类型定义(弱类型)
def version = 1 //类似js中的 var
2.assert 断言语句任何地方都可以执行
assert version == 1
3.括号是可选的
println(version)
println version //等同于上
4.字符串的三种定义方式
def s1 = 'p' //仅仅是字符串
def s2 = "gradle version is ${version}" //可以插入变量
def s3 = '''
p
c
l''' //可以换行
//println s1 + s2 + s3
5.集合API
list:
def buildTools = ['ant','maven'] //对应ArrayList
buildTools << 'gradle' //追加
assert buildTools.getClass() == ArrayList
assert buildTools.size() == 3
println buildTools
map
def buildYears = ['ant':2000,'maven':1999] //对应LinkedHashMap
buildYears.gradle = 1993 //追加
println buildYears.ant
println buildYears['gradle']
println buildYears.getClass().getName()
6.闭包
就是一个代码块,类似方法,可以有参数或无参数,可以被赋值给一个变量,也可以当做参数传递给一个方法,像普通方法一样调用,构建脚本中一般被当做方法参数来使用
//包含参数的闭包
def c1 = {
//参数类型可以省略,箭头后面是方法体
v ->
println v
}
//不包含参数
def c2 = {
println 'hello~'
}
//使用闭包作为参数的方法
def method1(Closure closure){
closure('param')
}
def mothod2(Closure closure){
closure()
}
method1(c1)
mothod2(c2)
构建脚本概要
构建块:
Gradle 构建中两个基本概念是 “项目”(project)和 “任务”(task),每个构建至少包含一个项目,项目中包含一个或者多个任务。在多项目构建中,一个项目可以依赖于其他项目;类似的,任务可以形成一个依赖关系图,来确保它们的执行顺序。
项目(project)
一个项目代表一个正在构建的组件(如 jar 文件),当构建启动后,Gradle 会基于 build.gradle 实例化一个org.gradle.api.Project 类,并且能够通过 project 变量使其隐式可用。
方法
- apply:应用一个插件,是 project 中的一个方法
- dependencies:申明项目依赖于哪些 jar 包或项目
- repositories:去哪个仓库找要依赖的 jar 包
- task:声明项目中有什么任务
- ext:定义并引用,可以使用来统一管理不同 module 的版本号
- gradle.properties:键值对形式申明一些属性并可引用
Groovy基础例子
apply plugin:'java'
构建脚本中默认是有一个project实例的,构建脚本里面所有的代码默认的作用域都是project,apply() 为 project 实例中的方法
version = 0.1
version 为 project 实例中的一个属性
repositories{
mavenCentral()
}
repositories也是一个方法;{ mavenCentral() }闭包作为一个参数调用该方法
dependencies{
compile 'commons-codec:commons-codec:1.6'
}
dependencies也是一个方法,{compile ‘commons-codec:commons-codec:1.6’ } 这也是一个闭包作为参数调用该方法
任务
对应org.gradle.api.Task,主要包括任务动作和任务依赖。任务动作定义了一个最小的工作单元(代码块)。任务还可以定义依赖于其他任务、动作序列和执行条件。
dependsOn: 申明任务依赖
doFirst: 在任务列表的最前面添加一个动作条件
doLast <<: 在任务列表的最后面添加一个动作
一个任务里可以执行多次 doFirst、doLast(动作列表里可包含多个动作)
setting.gradle
用来管理多项目构建
自定义任务
申明一个闭包,功能:根据传进来的路径创建文件
def createDir = { path -> File file = new File(path); if (!file.exists()){ file.mkdirs() } }
使用 task 申明一个任务-创建java目录
task makeJavaDir(){ //定义存放目录的路径 def paths = ['src/main/java','src/main/resources','src/test/java','src/test/resources'] //给任务添加动作,在动作列表的前边插入一个动作 //遍历这个目录结构,然后创建对应的目录 doFirst{ paths.forEach(createDir) } }
使用 task 申明一个任务-创建web目录
java工程有的目录结构,web工程都有只是多了一个webapp目录,所以创建web目录任务依赖创建java目录任务,仅仅创建自己特有的目录就可以了
task makeWebDir(){ //申明该任务依赖 makeJavaDir 这个任务 dependsOn 'makeJavaDir' //创建自己特有的目录 def paths = ['src/main/webapp','src/test/webapp'] //在这里跟doFirst作用一致,顺序相反而已 doLast{ paths.forEach(createDir) } }
完成后可在 Gralde-other 中查看,写完未出现的话刷新一下
构建生命周期
- 初始化
初始化项目、有哪些项目需要参与到构建当中 - 配置
生成 task 的依赖关系跟执行图
dependsOn需要在这个阶段 - 执行
执行动作代码
三个阶段后面都进阶一个 Hook 方法,可以进行处理一些自定义事件
依赖管理
几乎所有的基于JVM的软件项目都需要依赖外部类库来重用所有的功能。自动化的依赖管理可以明确依赖的版本,可以解决因依赖性传递带来的版本冲突
依赖的传递性:
B依赖,如果C依赖B,那么C依赖A
依赖阶段配置:
源代码阶段:compile、runtime
测试代码阶段:testCompile、testRuntime依赖阶段关系:
运行时阶段都是extends扩展与编译时阶段的、编译时依赖的jar包在运行时都会依赖、运行时依赖的在编译时不会依赖、源代码依赖的测试代码都会依赖、测试代码依赖的源代码不一定会依赖(具体搜索查看图解)
使用编译时依赖:compile,则会在编译和运行时都寄来
而使用运行时依赖:runtime则编译时不会依赖、只会在运行时依赖
当有多个仓库的时候,会按仓库的顺序去查找jar包,如果第一个仓库中查找到jar包了就不会从后面的仓库去查找、如果第一个没找到就会从后面的去查找依赖冲突:
当同一项目的多个依赖项中依赖了其他相同的依赖库,但是版本不一致
解决冲突(Gradle默认处理方式是依赖最高版本的jar包,所以一般不需要我们自己处理)
使用 exclude 排除传递性依赖
使用相同的版本:强制制定一个版本
以下配置可以修改Gradle默认处理策略,当有依赖冲突的时候回报错,help-dependices可以看到依赖详情;configurations.all{ resolutionStrategy{ failOnVersionConflict() //这里强制制定版本 force'group:name:version' } }
- 多项目构建
项目模块化
在企业项目中,包层次和类关系比较复杂,把代码拆分成模块通常是最佳实践,这需要你清晰的划分功能的边界,比如把业务逻辑和数据持久化拆分开来。项目符合高内聚低耦合时,模块化就变得很容易,这是一条非常好的软件开发实践.
实例
所有项目都应用java插件
每一个moudle里都有一个 apply plugin:’java’,在根项目的build.gradle中配置
注:(allprojects 应用在所有的Project中,包括root-project本身)allprojects { apply plugin:'java' }
web子项目打包成 war 包
在web子模块单独:apply plugin:'war'
所有项目添加统一依赖,如junit,这样就不用每个模块都写一遍
注:(subprojects 用于配置所有的子Project(不包含根Project))
subprojects { dependencies { testCompile 'junit:junit:4.12' } }
统一配置 group 和 version
gradle.properties文件中配置:需要添加=号
group = 'com.xxx.xxx' version = 1.0-SNAPSHOT
根项目的build.grdle可以配置每个模块统一的配置,子项目只需要配置自己个性化的配置,这样有利于统一管理和维护
如果想构建所有的项目,就在根项目下执行对应的任务,如果想执行单个项目的任务,就在单个项目下执行对应的任务
setting.gradle:用来管理根项目和子项目
发布到仓库(本地和远程)
maven-publish插件、配置、执行发布任务。