我们习惯了使用Maven构建工具,现在市面上大多数也都是使用的Maven,但是Gradle的出现,究竟哪个更好用哪个更有优势呢?
maven官网:Maven官网
maven配置环境(MacOS系统):
// 输入命令
vim ~/.bash_profile
//打开后配置环境变量,点i为输入,复制下面两句,MAVEN_HOME,换成自己下载的路径
export MAVEN_HOME=/Users/…/apache-maven-3.6.3
export PATH=$PATH:$MAVEN_HOME/bin
//配置完毕后 esc + :wq 保存退出
//输入 使配置生效
source ~/.bash_profile
//测试是否成功,要先装好jdk哦
mvn -version或者 mvn -v
效果图:
Gradle官网:Gradle官网
gradle配置环境(MacOS系统):
// 输入命令
vim ~/.bash_profile
//打开后配置环境变量,点i为输入,复制下面两句,GRADLE_HOME,换成自己下载的路径
GRADLE_HOME=/users/.../gradle-7.0
export GRADLE_HOME
export PATH=$PATH:$GRADLE_HOME/bin
//配置完毕后 esc + :wq 保存退出
//输入 使配置生效
source ~/.bash_profile
//测试是否成功,要先装好jdk哦
gradle -version
效果图:
都是项目管理工具,都可以解决构建管理、依赖管理问题、项目自动化打包部署等操作。
用GroupID(组id)、ArtifactID(项目id)和Version(版本号)配合为唯一标识一个依赖项。
远程中央仓库(世界公用)、本地仓库(本地计算机上可创建)和私服(公司搭建的仓库)。
都可以对整个项目或其中特定子项目中进行配置。
source、resource、test source、test resource等相应资源的标准结构。
普通java项目:如图
Maven于2004年诞生,而Gradle于2012年。
Maven出现是为了解决2000年诞生的项目构建工具:Ant存在的问题
而Gradle出现也是为了解决Maven存在的问题。
maven使用xml文件配置项目,可以做到各种提供的配置选择,比如自动化编译、打包、部署,运行,但是缺乏自定义的拓展性,而gradle使用build.gradle配置文件,可以使用特定脚本语言groove编写自定义脚本加入到自动化构建流程中。
在Maven中需要定义POM(Project Object Model)作为一组module的通用配置模型,常见pom.xml配置项:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.examplegroupId>
<artifactId>demoartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>mavenDemoname>
<description>mavenDemo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
...
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
exclude>
excludes>
configuration>
plugin>
...
plugins>
build>
project>
Gradle在build.gradle文件中常见配置项:
group 'com.example'
version '0.0.1-SNAPSHOT'
apply plugin: 'java'
sourceCompatibility = 1.8
//配置仓库,可选择先后方法,如先使用本地仓库,如果没有则使用自定义路径仓库,如果还是没有则使用中央仓库
repositories {
mavenLocal()
maven { url "http://maven.ipo.com/nexus/content/groups/public/" }
mavenCentral()
}
//依赖坐标
dependencies {
def springVersion = "4.2.8.RELEASE"
//Spring相关依赖依赖
compile("org.springframework:spring-aop:$springVersion",
"org.springframework:spring-orm:$springVersion"...)
//日志相关依赖
compile(//"commons-logging:commons-logging:1.2",
"log4j:log4j:1.2.17")
}
//使用TestNG生成测试报告
test {
useTestNG {
//打印正在运行的单元测试及结果
testLogging.events = ["failed", "passed", "skipped"]
//打印失败日志到控制台
testLogging.showStandardStreams = true
//配置testng.xml文件位置
suites(file("src/main/resources/qacontext/testng.xml"));
}
beforeTest { descriptor ->
logger.lifecycle("Running test: " + descriptor)
}
onOutput { descriptor, event ->
logger.lifecycle("Test: " + descriptor + " produced standard out/err: " + event.message)
}
}
如果依赖的jar很多,是不是gardle看起来更加流畅。
在Maven中,一个依赖项有6种scope,分别是compile、provided、runtime、test、system、import。其中compile为默认。而gradle将其简化为4种,compile、runtime、testCompile、testRuntime。
如代码“testCompile ‘junit:junit:4.+’”,在Gradle中支持动态的版本依赖,在版本号后面使用+号可以实现动态的版本管理。
Maven中需要定义parent POM(Project Object Model)作为一组module的通用配置模型,在POM文件中可以使用标签来定义一组子模块。parent POM中的build配置以及依赖配置会自动继承给子module。
如:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>demo_parentartifactId>
<packaging>pompackaging>
<version>1.0-SNAPSHOTversion>
<modules>
<module>demo_eurekamodule>
<module>demo_gatewaymodule>
<module>demo_servicemodule>
<module>demo_service_apimodule>
<module>demo_webmodule>
<module>demo_commonmodule>
<module>demo_canalmodule>
modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Greenwich.SR1version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
project>
Gradle中,需要在parent的build.gradle中使用allprojects和subprojects代码块分别定义应用于所有项目或子项目中的配置。对于子模块中的定义放置在settings.gradle文件中,每一个模块代表project的对象实例。
如父项目使用allprojects方法自动继承给子项目:
在setting.settings.gradle中配置父项目和所有的子项目关系:
build.gradle可以使用groove语言自定义编写插件、脚本加入到构建流程中。
简单例子,比如我们要在编译所有项目之前需要在控制台打印输出一下所编译的项目的项目名称和版本号:未完待续//todo
我们对于同一个项目使用不同的构建工具,一起来测试一下相同操作的的时间。
我简单写了几个.java源码,maven项目和gradle项目代码、目录结构、依赖坐标都相同。我们对同一种操作多次尝试运行–
Maven:125ms
Gradle:25ms
Maven:450ms
Gradle:34ms
Maven:739ms
Gradle:325ms
Maven:885ms
Gradle:65ms
可见,这只是我随便添加了几个java文件,如果是企业级的项目,差距应该会更大。
他们虽然都是使用Java开发的工具,但为什么Gradle的速度更快呢?因为执行原理不同,因为Maven和Gradle核心代码都是用Java语言编写的,所有他们执行任何任务(Lifecycle)都是启动一个JVM进程。一个JVM的启动是很慢,因为需要加载所有的jar包,但是区别:
Maven:要执行一个任务(如compile),需要启动一个JVM进程,任务完成后,JVM进程销毁。
Gradle:要执行一个任务(如compile),首先会启动一个ClientJVM,它非常轻量,负责接收、转发请求,只去后台链接称为DaemonJVM通信,把任务和参数发送给Daemon,Daemon执行结束后,结果返回给ClientJvm。然后ClientJVM被销毁,而Daemon则会一直存在,默认存在3小时,如果需要多次运行,只需要第一次预热,减少了启动开销。如图:
gradle在多个版本的同一个类型jar包选择中,如果有版本高的,他会默认选择最高版本的jar,可能会出现间接依赖的高版本的包,并不是你想要的,所以会出现编译报错哦。
解决方案,使用force=true,来强制指定某个版本的jar包。