Gradle是什么:
一个开源的
项目自动化构建工具
,建立在 Apache Ant 和 Apache Maven 概念的基础上,并引入了基于 Groovy 的特定领域语言(DSL),而不是使用 XML 形式管理构建脚本。(构建工具:依赖管理、自动化运行测试、打包到指定位置)
目录结构:
- bin:Gradle的可执行文件
- init.d:初始化执行脚本
- lib:Gradle本身依赖的jar包
- media:图标文件
Groovy是什么
Groovy是用于Java虚拟机的一种敏捷的动态语言,它是一种成熟的面向对象编程语言,既可以用于面向对象编程,又可以用作纯粹的脚本语言。使用该语言不必编写过多的代码,同时又具有闭包和动态语言中的其他特征。
与Java比较
- Groovy完全兼容Java的语法
- 分号是可选的
- 类、方法默认是public的
- 编译器给属性自动添加getter/setter方法
- 属性可以直接用点号获取
- 最后一个表达式的值会被作为返回值
- ==等同于equals(),不会有NullPointerExceptions
高效的Groovy特性
- assert语句,断言操作
- 可选类型定义
- 可选的括号
- 字符串
- 集合API
- 闭包
Groovy编程案例
public class ProjectVersion{
private int major;
private int minor // 分号可选
public ProjectVersion(int major, int minor){
this.major = major
this.minor = minor ;
}
public int getMajor(){
major // return可省
}
public int setMajor(int major){
this.major = major ;
}
}
ProjectVersion v1 = new ProjectVersion(1, 1) ;
println v1.minor
ProjectVersion v2 = null ;
println v2 == v1 ;
// 1、可选的类型定义
def version = 1
// 2、assert
assert version == 2
// 3、括号是可选的
println(version) // 可以写成 println version
// 4、字符串
def s1 = 'imooc'
def s2 = "gradle version is ${version}"
def s3 = '''my name
is
imooc''' // 支持换行
println s1
println s2
println s3
// 5、集合api
// list
def buildTools=['ant', 'maven']
buildTools << 'gradle' // 追加一个元素
assert buildTools.getClass() == ArrayList
assert buildTools.size() == 3
// map
def buildYears = ['ant':2000, 'maven':2004]
buildYears.gradle = 2009
println buildYears.ant
println buildYears['gradle']
println buildYears.getClass()
// 6、闭包(代码块)
def c1 = {
v ->
print v
}
def c2 = {
print 'hello'
}
def method1(Closure closure){
closure('param')
}
def method2(Closure closure){
closure()
}
method1(c1) ;
method2(c2) ;
groovy构建脚本
// 构建脚本中默认都是有个Project实例的,构建脚本中的代码默认作用域都是Project
apply plugin: 'java' // plugin: 'java'是命名参数,apply 是Project实例上有一个方法,省略了括号
version = '0.1' // Project实例有个属性version
repositories { // 一个闭包作为参数调用此方法
mavenCentral()
}
dependencies { // 同样是一个闭包
compile 'commons-codec : commons-codec : 1.6 '
}
Gradle工程目录结构
group 'com.imooc.gradle'
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'war' // 使用插件构建war包,注释改行可构建jar包
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name:'junit', version: '4.11'
}
构建脚本概要
构建块
Gradle构建中的两个基本概念是项目(project)和任务(task),每个构建至少包含一个项目,项目中包含一个或多个任务。在多项目构建中,一个项目可以依赖于其他项目;类似的,任务可以形成一个依赖关系图来确保他们的执行顺序。
项目(project)
一个项目代表一个正在构建的组件(比如一个jar文件),当构建启动后,Gradle会基于build.gradle实例化一个org.gradle.api.Project类,并且能够通过project变量使其隐式可用。
- 属性:group、name、version(组件坐标)
- 重要方法:apply(应用插件)、 dependencies(申明项目依赖的jar或其他项目)、repositories(去哪个仓库获取jar包)、task(申明项目里的人物)
- 属性的其他配置方式:ext(定义属性)、gradle.properties(以键值对申明属性)
任务(task)
任务对应org.gradle.api.Task。主要包括任务动作和任务依赖。任务动作定义了一个最小的工作单元。可以定义依赖于其他任务、动作序列和执行条件。
- dependsOn(申明任务依赖)
- doFirst(task动作列表最前面添加动作)、doLast (简写方式:<<,动作列表末尾添加动作)
自定义任务
// 2、创建一个闭包,根据路径创建文件
def createDir = {
path ->
File dir = new File(path) ;
if(!dir.exists()){
dir.mkdirs() ;
}
}
// 1、自定义任务,自动创建目录结构的功能
task makeJavaDir(){
def paths = ['src/main/java', 'src/main/resources', 'src/test/java', 'src/test/resources'] ;
doFirst{
paths.forEach(createDir) ;
}
}
task makeWebDir(){
dependsOn = 'makeJavaDir' ; // 依赖
doLast{
paths.forEach(createDir) ;
}
}
- 初始化:Gradle会根据构建脚本创造一个Project类,并且在这个脚本内隐式可用。多项目构建中,初始化所有将要参与构建中的项目。
- 配置:根据配置代码(简单说:除了动态代码都是配置代码),生成task依赖顺序以及执行顺序。
- 执行阶段:执行动作代码
依赖管理
几乎所有的基于JVM的软件项目都需要依赖外部类库来重用现有的功能。自动化的依赖管理可以明确依赖的版本,可以解决因传递性依赖带来的版本冲突。
工件坐标
- group、name、version
常用仓库
- mavenLocal/mavenCentral/jcenter
- mavenCentral/jcenter:公共仓库
- mavenLocal:本机使用过的jar的仓库
- 自定义maven仓库
- 文件仓库(本地文件路径作为仓库:不建议使用)
依赖的传递性
- B依赖A,如果C依赖B,那么C依赖A(造成版本冲突的原因)
依赖管理的阶段
依赖阶段配置
- compile、runtime(源代码)
- testCompile、testRuntime(测试代码)
repositories { // 仓库,依赖仓库按顺序进行依赖优先级
maven{ // 私服
url '私服地址'
}
mavenLocal()
mavenCentral()
}
dependencies {
compile 'ch.qos.logback:logback-classic:1.2.1'
testCompile group: 'junit', name:'junit', version: '4.11'
}
依赖冲突
解决冲突
查看依赖报告
排除传递性依赖
强制一个版本
-
修改默认解决策略(Gradle默认依赖最高版本来解决版本冲突)
configurations.all{ resolutionStrategy{ failOnVersionConflict() // 使构建失败,可以知道哪些出现版本冲突 } }
-
排除传递性依赖
compile('org.hibernate:hibernate-core:3.6.3.Final'){ exclude group:"org.slf4j", module:"slf4j-api" // transitive=false }
-
强制指定一个版本
configurations.all{ resolutionStrategy{ force 'org.slf4j:slf4j-api:1.7.24' } }
项目模块化
在企业项目中,包层次和类关系比较复杂,把代码拆分成模块通常是最佳实践,这需要你清晰的划分功能的边界,比如把业务逻辑和数据持久化拆分开来。项目符合高内聚低耦合时,模块化就变得很容易,这是一条非常好的软件开发实践。
配置要求
- 所有项目应用Java插件
- web子项目打包成WAR
- 所有项目添加logback日志功能
-
统一配置公共属性
settings.gradle:管理多项目构建
rootProject.name = 'todo' // 根项目
include 'repository' // 子项目
include 'model'
include 'web'
web项目:
dependencies {
compile project(":repository")
testCompile group: 'junit', name:'junit', version: '4.11'
}
todo项目:
allprojects{ // 全局配置
apply plugin: 'java'
sourceCompatibility = 1.8
}
// 所有项目添加logback日志功能
subprojects{
repositories{
mavenCentral()
}
dependencies{
compile 'ch.qos.logback:logback-classic:1.2.1'
testCompile group: 'junit', name:'junit', version: '4.11'
}
}
统一配置group和version
根项目添加:gradle.properties文件
group = 'com.imooc.gradle'
version = 1.0-SNAPSHOT
自动化测试
一些开源的测试框架,比如JUnit,TestNG能够帮助你编写可复用的结构化的测试,为了运行这些测试,你要先编译它们,就像编译源代码一样。测试代码的作用仅仅用于测试的情况,不应该被发布到生产环境中,需要把源代码和测试代码分开来。
项目布局
测试配置
dependencies{
testCompile 'junit:junit:4.11'
}
测试发现
- 任何继承自junit.framework.TestCase或groovy.util.GroovyTestCase的类
- 任何被@RunWith注解的类
- 任何至少包含一个被@Test注解的类
发布到本地仓库和远程仓库
allprojects{
apply plugin: 'java'
sourceCompatibility = 1.8
apply plugin: 'maven-public'
publishing{
publications{
myPublish(MavenPublication){ // 自定义函数
from components.java
}
}
repositories{
maven{
name "myRepo" // 自定义仓库名
url "" // 自己仓库
}
}
}
}