Gradle是基于JVM的,故本地必须要有JDK
从Gradle官网下载Gradle,https://gradle.org
配置环境变量GRADLE_HOME
添加到PATH
export GRADLE_HOME=/Users/wangzhe/Documents/class/gradle-4.10.2 export PATH=$PATH:$GRADLE_HOME/bin
验证是否安装成功gradle -v
'xxxx'
"xxxx"
'''xxxx'''
//定义工程版本对象——点击运行按钮进行运行,结果会输出到console控制台 public class ProjectVersion{ private int major;//大版本 private int minor;//小版本 ProjectVersion(int major, int minor) { this.major = major this.minor = minor } int getMajor() { major } void setMajor(int major) { this.major = major } // // int getMinor() { // return minor // } // // void setMinor(int minor) { // this.minor = minor // } } ProjectVersion v1 = new ProjectVersion(1,2); println(v1.minor)//2 自动创建getter和setter println(v1.major)//1 将最后一个表达式看做返回值 ProjectVersion v2 = null println(v2 == v1)//false 使用==判断时相当于equals()方法,不会抛出空指针异常
//Groovy 高效特性 //1. 可选的类型定义 def version = 1 //2. assert //assert version==2//失败的断言,在任何地方都可以执行 //3. 括号是可选的 println(version)//1 println version //1 //4. 字符串 def s1 = 'Jack'//仅仅是一个字符串 def s2 = "Gradle version is ${version}"//可以使用${}插入变量 def s3 = '''Jack is so smart.'''//可以换行,输出的结果也是换行的 println s1//Jack println s2//Gradle version is 1 println s3//Jack is so smart //5. 集合API // list def buildTools = ['ant','maven'] buildTools << 'gradle' //表示向buildTools中追加元素 assert buildTools.getClass() == ArrayList//不会出现异常,表示是ArrayList类型 assert buildTools.size() == 3//不会出现异常,表示当前集合中有三个元素 //map——对应java中的LinkedHashMap def buildYears = ['ant':2000,'maven':2004] buildYears.gradle = 2009//表示向buildYears的map中追加元素 println buildYears.ant//2000 println buildYears['gradle']//2009 println buildYears.getClass()//class java.util.LinkedHashMap //6.闭包——通常当做方法参数来使用 //c1的参数为v,方法体打印v;c2不包含参数 def c1 = { v -> println v } def c2 = { print 'hello' } def method1(Closure closure){ closure('param') } def method2(Closure closure){ closure() } method1(c1)//param method2(c2)//hello
//Gradle的构建脚本 //每个Gradle的构建脚本都有个Project实例,且每个Gradle构建脚本中所有代码默认的作用域都是Project //plugin:'java'表示plugin这个参数的值为java;apply是一个方法 apply plugin:'java' //version表示Project上有一个属性叫version值等于0.1 version = '0.1' //repositories是一个方法,mavenCentral()作为参数调用repositories方法 repositories{ mavenCentral() } //dependencies是一个方法,compile 'commons-codec:commons-codec:1.6'闭包作为参数调用dependencies方法 dependencies{ compile 'commons-codec:commons-codec:1.6' }
File -> new -> Project -> Gradle(Java 1.8) -> 输入GroupId和ArtifactId -> use local gradle distribution并选择对应的本地gradle路径 -> 填入项目名 -> Finish
Gradle项目目录[固定的目录结构]
.gradle
和.idea
是编译器自动生成的文件,可忽略
src
表示代码目录main源代码目录;test测试代码目录
build.gradle
文件
//表示使用java的插件 plugins { id 'java' } group 'com.gradletest' version '1.0-SNAPSHOT' //源文件适应的版本 sourceCompatibility = 1.8 //仓库 repositories { mavenCentral() } //依赖管理 dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' }
setting.gradle
文件
在main/java下创建com.gradletest.todo.TodoItem.java
用于定义Todo类
package com.gradletest.todo; public class TodoItem { //待办事项的名称 private String name; //已完成 private boolean hasDone; public TodoItem(String name) { this.name = name; hasDone = false; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isHasDone() { return hasDone; } public void setHasDone(boolean hasDone) { this.hasDone = hasDone; } @Override public String toString() { return "TodoItem{" + "name='" + name + '\'' + ", hasDone=" + hasDone + '}'; } }
package com.gradletest.todo; public class TodoItem { //待办事项的名称 private String name; //已完成 private boolean hasDone; public TodoItem(String name) { this.name = name; hasDone = false; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isHasDone() { return hasDone; } public void setHasDone(boolean hasDone) { this.hasDone = hasDone; } @Override public String toString() { return "TodoItem{" + "name='" + name + '\'' + ", hasDone=" + hasDone + '}'; } }
在main/java下创建com.gradletest.todo.App.java
用于执行对应的todo操作
package com.gradletest.todo; import java.util.Scanner; public class App { public static void main(String [] args){ int i = 0; Scanner scanner = new Scanner(System.in); while(++i>0){ System.out.println(i+".please input todo item name:"); TodoItem item = new TodoItem(scanner.nextLine()); System.out.println(item); } } }
package com.gradletest.todo; import java.util.Scanner; public class App { public static void main(String [] args){ int i = 0; Scanner scanner = new Scanner(System.in); while(++i>0){ System.out.println(i+".please input todo item name:"); TodoItem item = new TodoItem(scanner.nextLine()); System.out.println(item); } } }
使用自动化构建工具Gradle来构建jar包
点击右侧Gradle->项目名->Tasks->build
点击jar会创建build包并可以在libs路径下看到指定打包好的jar包
在命令行执行jar包的对应类java -classpath build/libs/todo-1.0-SNAPSHOT.jar com.gradletest.todo.App
,结果就是直接运行App.java的结果
添加webapp包及包下的WEB-INF与其中的web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1" metadata-complete="true"> <!--metadata-complete为true时,该web不会加载注解配置的web组件(如Servlet、Filter、Listener等)--> <!--配置Web应用的首页列表--> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>index.htm</welcome-file> </welcome-file-list> </web-app>
在webapp下编写一个简单的index.html用于测试
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 这里是首页 </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 这里是首页 </body> </html>
在build.gradle中添加apply plugin:'war'
的war插件
plugins { id 'java' } group 'com.gradletest' version '1.0-SNAPSHOT' apply plugin:'war'//添加war插件 //源文件的版本 sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' }
可以发现在右侧Gradle的build中会多一个war选项,点击即会将项目打成war包,war包放到Tomcat下即可运行
war包放到webapp中后会自动解压缩
META-INF
、WEB-INF
、index.html
,第一个目录为打包成war包时自动生成的,后两个文件为webapp下的内容WEB-INF
中存在classes文件和web.xml文件构建块
项目(project)
一个项目代表一个正在构建的组件(比如一个jar文件),当构建启动后,Gradle会基于build.gradle实例化一个org.gradle.api.Project类,并且能够通过project变量使其隐式可用。
【即在build.gradle中所有的变量方法的调用都是在Project类中定义】
//例如: group 'com.gradletest' //等同于project.group = 'com.gradletest'
任务(task)
任务对应org.gradle.api.Task
,主要包括任务动作和任务依赖。任务动作定义了一个最小的工作单元。可以定义依赖其他任务、动作序列和执行条件。
<<
)在任务列表的最末尾添加动作Tasks中的war是war插件的任务,其余的是java插件带的任务
当我们执行jar的task任务时,只执行了jar任务,但是前面执行了,说明jar任务依赖其余三个任务:compileJava、processResources、classes。下图中的UP-TO-DATE表示从上次执行jar后信息没有改变,所以跳过了相关任务的执行。
在一个项目里面任务不是必须的,大多数情况下我们都使用插件提供的功能,如果插件完成不了的任务我们会自定义任务
settings.gradle
文件用来管理多项目构建
自定义创建包任务
定义创建包的任务,并声明文件名称,在任务类中添加创建文件夹闭包的动作
//定义闭包执行根据文件夹名称创建文件夹操作 def createDir= { path -> File dir = new File(path); if(!dir.exists()){ dir.mkdirs(); } } //创建一个新建文件夹的任务 task makeJavaDir() { def paths = ["selfdefine/java","selfdefine/test"] //在动作列表的最前面插入一个动作 doFirst{ paths.forEach(createDir) } }
自定义任务在右侧Gradle->Tasks->other
下可以查看,并点击运行
则会在项目根路径下添加对应的文件夹
自定义创建web包任务(使用任务的依赖)
定义创建web包任务,利用dependsOn设定任务依赖makeJavaDir任务,并添加创建文件夹闭包的动作
task makeWebDir(){ dependsOn 'makeJavaDir' def paths = ["src/main/webapp","src/test/webapp"] doLast{ paths.forEach(createDir) } }
同样在Gradle->Tasks->other
查看并执行任务
则会首先执行makeJavaDir的任务,再执行当前任务中定义的动作
第一个阶段:初始化阶段
第二个阶段:配置阶段
用来生成Task的依赖顺序和执行顺序(根据配置代码,简单可以理解为除了动作代码之外全是动作代码)
初始化任务
举例:
task loadVersion{ project.version = '1.0' }
第三个阶段:执行阶段
执行task的动作代码
举例:
task loadVersion << { print 'success' }
钩子方法(平常使用时,不常用到)
概述:几乎所有的基于JVM的软件项目都需要依赖外部类库来重用现有的功能。自动化的依赖管理可以明确依赖的版本,可以解决因传递性依赖带来的版本冲突。
工件坐标:工件简单的可以理解为一个jar包,坐标为三个属性group、name、version。通过三个属性确定唯一的jar包。
常用仓库:仓库就是存放jar包的地方。
依赖的传递性
B依赖A,如果C依赖B,那么C依赖A
正是由于依赖的传递性,会出现版本冲突
自动化依赖管理
依赖管理的阶段
实例使用依赖
将原dependencies中的依赖junit方式改成compile,则可以通过Gradle->Source Sets->main->Dependencies
查看到对应依赖的jar包(即从测试编译阶段变成了编译阶段的依赖)
Gradle
中的项目名右击,选择auto-import
,则当修改对应依赖阶段即相关操作时自动刷新
什么时候使用编译依赖,什么时候使用运行依赖?
大部分都是使用编译依赖,因为我们编译时需要使用,运行时也需要使用。
添加依赖
在https://search.maven.org/搜索对应需要的依赖,本例添加的是日志记录依赖
从网站上获得对应的依赖工件坐标,并引入编译阶段依赖
compile 'ch.qos.logback:logback-classic:1.3.0-alpha4'
依赖的写法 'ch.qos.logback:logback-classic:1.3.0-alpha4'
等同于group:'ch.qos.logback',name:'logback-classic',version:'1.3.0-alpha4'
由于logback依赖又依赖别的jar包,故可以通过Dependencies中看出其依赖的其他jar
使用添加的依赖
package com.gradletest.todo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Scanner; public class App { static Logger log = LoggerFactory.getLogger(App.class); public static void main(String [] args){ int i = 0; Scanner scanner = new Scanner(System.in); while(++i>0){ log.info("{}.please input todo item name:",i);//以logback的日志格式打印 TodoItem item = new TodoItem(scanner.nextLine()); System.out.println(item); } } }
package com.gradletest.todo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Scanner; public class App { static Logger log = LoggerFactory.getLogger(App.class); public static void main(String [] args){ int i = 0; Scanner scanner = new Scanner(System.in); while(++i>0){ log.info("{}.please input todo item name:",i);//以logback的日志格式打印 TodoItem item = new TodoItem(scanner.nextLine()); System.out.println(item); } } }
则会以日志的形式进行输出18:38:19.727 [main] INFO com.gradletest.todo.App - 1.please input todo item name:
添加仓库
仓库会按顺序查找jar包,第一个查找到了就不往下查找,没查找到就继续往下查找
使用maven私服——通常有私服都会将私服放在第一位,先找私服
maven{ url ''//私服的地址 }
可以配合多个仓库使用
repositories { //按顺序查找jar包,第一个查找到了就不往下查找,没查找到就继续往下查找 //使用maven私服——通常有私服都会将私服放在第一位,先找私服 maven{ url ''//私服的地址 } //可以配多个仓库 mavenLocal() //表示从mavenCentral仓库获取jar mavenCentral() }
解决版本冲突的具体步骤
Gradle会默认使用冲突版本中最高版本的jar包
修改Gradle默认解决策略(当版本冲突时,设置为构建失败)
configurations.all{ resolutionStrategy{ failOnVersionConflict() } }
自行解决冲突
排除传递性依赖,如下:
compile('org.hibernate:hibernate-core:3.6.3.Final'){ exclude group:'org.slf4j',module:'slf4j-api'//排除具体jar包的依赖,module即是坐标中的name属性 //transitive=false 排除所有的传递依赖(少见) }
强制指定一个版本,如下:
configurations.all{ resolutionStrategy{ force 'org.slf4j:slf4j-api:1.7.24'//强制指定版本 } }
可以使用Gradle->项目->help->dependencies
查看所有jar包的依赖
项目模块化:在企业项目中,包层次和类关系比较复杂,把代码拆分成模块通常是最佳实践,这需要你清晰的划分功能的边界,比如把业务逻辑和数据持久化拆分开来。项目符合高内聚低耦合时,模块就变得很容易,这是一条非常好的软件开发实践。
TODO模块依赖关系
配置要求
构建项目
创建子模块项目右击->new Module->填写模块名->Finish
创建子模块的同时会自动将子模块信息include到settings.gradle中。多项目构建时,settings.gradle用来管理当前项目有哪些子项目,root为根项目。并根据右侧Gradle可以查看对应项目的相关信息。
rootProject.name = 'todo'//根项目名 include 'model' include 'repository' include 'web'
由于repository中需要操作model内容,故repository模块需要依赖model模块
//对子项目的依赖——特殊的写法project(":模块名") compile project(":model");
由于web需要依赖repository和model,但是repository依赖model,故web只需要依赖repository即可传递依赖获得model
compile project(":repository")
注意:子模块依赖方式采用compile project(':子模块名')
完成配置要求
所有项目应用java插件
将所有子项目的应用java插件的语句删除,统一在根项目的gradle中配置
//删除内容 plugins { id 'java' } sourceCompatibility = 1.8
在根项目的build.gradle中添加
allprojects{ apply plugin:'java' sourceCompatibility = 1.8 }
web子项目打包成WAR
将根项目的war插件删除,添加到web子项目的build.gradle中
apply plugin:'war'//添加war插件
查看右侧Gradle,只有web子项目有war的任务
所有子项目添加logback日志功能
在根项目的build.gradle中添加subprojects{}
并引入对应依赖【allprojects和subprojects中的配置跟build.gradle一样】
allprojects{ apply plugin:'java' sourceCompatibility = 1.8 } subprojects { repositories { //表示从mavenCentral仓库获取jar mavenCentral() } dependencies { //在https://search.maven.org/搜索对应需要的依赖,本例添加的是日志记录依赖 compile 'ch.qos.logback:logback-classic:1.3.0-alpha4' //表示在测试阶段依赖的jar包 compile group: 'junit', name: 'junit', version: '4.12' } } group 'com.gradletest' //等同于project.group = 'com.gradletest' version '1.0-SNAPSHOT' repositories { //表示从mavenCentral仓库获取jar mavenCentral() }
在子项目中删除引入的junit依赖,因为已经通过根项目配过了
//删除的语句 compile group: 'junit', name: 'junit', version: '4.12'
统一配置公共属性,如version、group等
在根项目下创建gradle.properties【注意不能写错】,并配置如下
group=com.gradletest version='1.0-SNAPSHOT'
删除所有子项目中的group和version配置
在根项目执行clean则会clean根项目及所有子项目的构建文件。如果相对指定子项目进行clean,则在指定子项目中执行clean。
在model模块执行jar,只会执行model模块中的内容。在web模块执行jar,会先编译model,之后编译repository,最后编译web模块内容。因为web依赖repository,repository依赖model。
总结:如果想构建所有的项目,则在根项目下执行对应任务;如果想构建单项目,则在单项目下执行对应的任务。
自动化测试
测试项目布局
测试配置
dependencies{ testCompile 'junit:junit:4.11' }
测试类被Gradle发现
发布到本地和远程仓库
项目发布的流程
添加插件
apply plugin:'maven-publish'
配置发布信息(要发布什么和仓库地址)
publishing{ publications{ //自定义发布方法名 myPublish(MavenPublication){ from components.java } } //配置远程仓库的信息 repositories { maven{ name "myPro"//仓库名称 url ""//仓库地址——通常用于私服(点击publishing中的publish发布到私服地址) } } }
执行发布任务Gradle->publishing->publishToMavenLocal
将项目发布到本地仓库中。若想发到公司私服,则可以配置repositories的url信息并点击publish选项。
Mac用户可以在~/.m2/repository/groupId路径
查看对应发布的项目