maven和gradle区别

https://www.cnblogs.com/huang0925/p/5209563.html

Gradle

开源自动化构建工具,基于特定领域语言Groove
Gradle安装请参考其他博客.

Groove基于java虚拟机的敏捷动态语言,面向对象的编程语言,也可以做脚本语言

  1. // buildscript 代码块中脚本优先执行
  2. buildscript {
  3. // ext 用于定义动态属性
  4. ext {
  5. springBootVersion = '1.5.2.RELEASE'
  6. }
  7. // 自定义 Thymeleaf 和 Thymeleaf Layout Dialect 的版本
  8. ext['thymeleaf.version'] = '3.0.3.RELEASE'
  9. ext['thymeleaf-layout-dialect.version'] = '2.2.0'
  10. // 自定义 Hibernate 的版本
  11. ext['hibernate.version'] = '5.2.8.Final'
  12. // 使用了 Maven 的中央仓库(你也可以指定其他仓库)
  13. repositories {
  14. //mavenCentral()
  15. maven {
  16. url 'http://maven.aliyun.com/nexus/content/groups/public/'
  17. }
  18. }
  19. // 依赖关系
  20. dependencies {
  21. // classpath 声明说明了在执行其余的脚本时,ClassLoader 可以使用这些依赖项
  22. classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
  23. }
  24. }
  25. // 使用插件
  26. apply plugin: 'java'
  27. apply plugin: 'eclipse'
  28. apply plugin: 'org.springframework.boot'
  29. // 指定了生成的打包的版本号
  30. version = '1.0.0'
  31. // 指定编译 .java 文件的 JDK 版本
  32. sourceCompatibility = 1.8
  33. // 默认使用了 Maven 的中央仓库。这里改用自定义的镜像库
  34. repositories {
  35. //mavenCentral()
  36. maven {
  37. url 'http://maven.aliyun.com/nexus/content/groups/public/'
  38. }
  39. }
  40. // 依赖关系
  41. dependencies {
  42. // 该依赖对于编译发行是必须的
  43. compile('org.springframework.boot:spring-boot-starter-web')
  44. //aop
  45. compile('org.springframework.boot:spring-boot-starter-aop')
  46. // 添加 Thymeleaf 的依赖
  47. compile('org.springframework.boot:spring-boot-starter-thymeleaf')
  48. // 添加 Spring Data JPA 的依赖
  49. compile('org.springframework.boot:spring-boot-starter-data-jpa')
  50. // 添加 MySQL连接驱动 的依赖
  51. compile('mysql:mysql-connector-java:6.0.5')
  52. // 添加 H2 的依赖
  53. runtime('com.h2database:h2:1.4.193')
  54. // 添加 Spring Data Elasticsearch 的依赖
  55. compile('org.springframework.boot:spring-boot-starter-data-elasticsearch')
  56. //jna依赖,否则项目启动时,会报classNotFound: native method disable的错误
  57. compile("com.sun.jna:jna:3.0.9")
  58. // 添加 Spring Security 依赖
  59. compile('org.springframework.boot:spring-boot-starter-security')
  60. // 添加 Thymeleaf Spring Security 依赖
  61. compile('org.thymeleaf.extras:thymeleaf-extras-springsecurity4:3.0.2.RELEASE')
  62. // 添加 Apache Commons Lang 依赖
  63. compile('org.apache.commons:commons-lang3:3.5')
  64. // 该依赖对于编译测试是必须的,默认包含编译产品依赖和编译时依
  65. testCompile('org.springframework.boot:spring-boot-starter-test')
  66. //添加markdown parser
  67. compile('es.nitaur.markdown:txtmark:0.16')
  68. //阿里 easyExcel
  69. compile("com.alibaba:easyexcel:1.0.4")
  70. }

构建
项目构建-maven_gradle - 图1
编译为jar后
项目构建-maven_gradle - 图2


maven 依赖管理

Maven

下载

Maven是Apache软件基金会唯一维护的一款自动化构建工具,专注于服务Java平台的项目构建依赖管理
https://archive.apache.org/dist/maven/maven-3/
由java编写,需要jre运行环境JAVA_HOME
根据 组织,项目,版本 从 仓库 找到jar
查找顺序 本地>私服>远程仓库

maven 常用命令

生成idea项目:mvn idea:idea

编译 ,测试 , 运行 , 打包, 安装 都交给maven构建
mvn clean清除target目录下文件
mvn compile编译出classes
mvn test 编译了源代码,测试代码,运行测试代码

mvn package 编译源代码,测试代码,运行测试代码,打包
mvn -Dtest package组合使用goal命令,如只打包不测试
package -Dmaven.test.skip=true -f pom.xml
项目构建-maven_gradle - 图3

mvn install 编译源代码,测试代码,运行测试代码,打包,放到本地仓库
mvn tomcat:run

版本 mvn versions:set -DnewVersion=1.3.1 -DgenerateBackupPoms=false

一、依赖

dependencyManagement 父pom的依赖管理
统一管理项目的版本号,确保应用的各个项目的依赖和版本一致

1. maven依赖范围

默认是compile,可选配置有test、provided、runtime、system、import

  1. <dependency>
  2. <groupId>junit</groupId>
  3. <artifactId>junit</artifactId>
  4. <version>4.7</version>
  5. <scope>test</scope>
  6. </dependency>

2. maven传递性依赖

在项目往往需要引入多个依赖, 而引入的依赖又会引入其他的依赖。

例如: 项目中引入了spring-core依赖, 而spring-core又依赖commons-logging。因为项目直接引入了spring-core依赖,则spring-core为项目的第一直接依赖, 而因为spring-core引入了commons-logging依赖, 则commons-logging为项目的一个传递性依赖。

有了Maven的传递性依赖机制,不用担心引入多余的依赖。 Maven会解析各个直接依赖的POM, 将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目中。

详细内容

3. maven依赖调解

例如, 项目A有这样的依赖关系:A->B->C->X(1.0), A->D->X(2.0), X是A的传递性依赖,但是两条依赖路径上有两个版本的X, 那么哪个X会被Maven解析使用呢?两个版本都解析显然是不对的,因为那会造成依赖重复,因此必须选择一个。Maven依赖调解的第一原则是:最短路径优先。该例中X(1.0)的路径长度为3,而X(2.0)的路径长度为2,因此X(2.0)会被解析使用。

依赖调解第一原则不能解决所有问题,比如这样的依赖关系: A->B->Y(1.0), A->C->Y(2.0), Y(1.0) 和 Y(2.0)的依赖路径长度是一样的,都为2,。 那么到底谁会被解析使用呢?在Maven2.0.8及之前的版本中,这是不确定的, 但是从Maven2.0.9开始,为了尽可能避免构建的不确定性,Maven定义了依赖调解的第二原则:两条路都是一样长,两个工程**在前面就是用哪个版本。但不一定生效 , 往往是这种路径一致造成jar冲突**。在依赖路径长度相同的情况下,在POM中依赖声明的顺序决定了谁会被解析使用,顺序最靠前的那个依赖优胜。该例中,如果B的依赖声明在C之前,那么Y(1.0)就会被解析使用。

4. maven可选依赖

假设有这样一个依赖关系,项目A依赖与项目B,项目B依赖于项目X和Y, B对于X和Y的依赖都是可选依赖: A->B, B->X(可选),
B->Y(可选)。 根据传递性依赖的定义,如果所有这三个依赖的范围都是compile,那么X, Y就是A的compile范围传递性依赖。然而,由于这里X,Y是可选依赖,依赖将不会得以传递。换句话说,X,Y将不会对A有任何影响。

为什么要使用可选依赖这一特性呢?可能项目B实现了两个特性,其中的特性一依赖于X,特性而依赖于Y,而且两个特性时互斥的,用户不能同时使用两个特性。比如B是一个持久层隔离工具包,它支持多种数据库,报错MySQL, PostgreSQL等,在构建这个工具包的时候, 需要这两种数据库的驱动程序,但在使用这个工具包的时候,只会依赖一种数据库。项目B的依赖声明如下:

<dependencies>
   <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.10</version>
      <optional>true</optional>
   </dependency>
   <dependency>
      <groupId>postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>8.4-701.jgbc3</version>
      <optional>true</optional>
   </dependency>
</dependencies>

上述代码片段中, 使用元素表示mysql-connector-java和postgresql这两个依赖为可选依赖,它们只会对当前项目B产生影响,当其他项目依赖于B的时候,这两个依赖不会被传递。因此,当项目A依赖于项目B的时候,如果其实际使用基于MySQL数据,那么项目A中就需要显示的声明mysql-connetor-java这一依赖,如下:

<dependencies>
   <dependency>
      <groupId>org.rogueq.mvnbook</groupId>
      <artifactId>project-b</artifactId>
      <version>1.0.0</version>
   </dependency>
   <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.10</version>
   </dependency>
</dependencies>

5. maven排除依赖

<exclusions>

6. maven归类依赖

<properties>

二、仓库

1. 仓库种类

Maven 仓库能帮助我们管理构件(主要是JAR),它就是放置所有JAR文件(WAR,ZIP,POM等等)的地方。

Maven 仓库有三种类型:

  • 本地(local) 它是在第一次执行 maven 命令的时候才被创建
  • 中央(central) 由 Maven 社区提供的仓库,其中包含了大量常用的库。
  • 远程(remote) 开发人员自己定制仓库
  • 私服Necus

Maven 仓库默认在国外, 国内使用难免很慢,我们可以更换为阿里云的仓库。
第一步:修改 maven 根目录下的 conf 文件夹中的 setting.xml 文件,在 mirrors 节点上,添加内容如下:

<mirrors>
    <mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>        
    </mirror>
</mirrors>

2. 搜索顺序

Maven 依赖搜索顺序
当我们执行 Maven 构建命令时,Maven 开始按照以下顺序查找依赖的库:

步骤 1 - 在本地仓库中搜索,如果找不到,执行步骤 2,如果找到了则执行其他操作。
步骤 2 - 在中央仓库中搜索,如果找不到,并且有一个或多个远程仓库已经设置,则执行步骤 4,如果找到了则下载到本地仓库中以备将来引用。
步骤 3 - 如果远程仓库没有被设置,Maven 将简单的停滞处理并抛出错误(无法找到依赖的文件)。
步骤 4 - 在一个或多个远程仓库中搜索依赖的文件,如果找到则下载到本地仓库以备将来引用,否则 Maven 将停止处理并抛出错误(无法找到依赖的文件)。

三、生命周期

四、面试题

1. “Mvn Clean Package”???

在这个命令中我们调用了maven的clean周期的clean阶段绑定的插件任务,以及default周期的package阶段绑定的插件任务
默认执行的任务有(maven的术语叫goal, 也有人翻译成目标,我这里用任务啦):

maven-clean-plugin:clean->
maven-resources-plugin:resources->
maven-compile-plugin:compile->
mavne-resources-plugin:testResources->
maven-compile-plugin:testCompile->
maven-jar-plugin:jar

2. Maven 依赖的解析机制是怎么样的?

解析发布(RELEASE)版本:如果本地有,直接使用本地的,没有就向远程仓库请求。
解析快照(SNAPSHOT)版本:合并本地和远程仓库的元数据文件 groupId/artifactId/version/maven-metadata.xml ,这个文件存的版本都是带时间戳的,将最新的一个改名为不带时间戳的格式供本次编译使用。
解析版本为 LATEST 过于复杂,且解析的结果不稳定,不推荐在项目中使用,感兴趣的同学自己去研究,简而言之就是合并groupId/artifactId/maven-metadata.xml 找到对应的最新版本和包含快照的最新版本。
? LASTEST、RELEASE、SNAPSHOT 的区别?

LASTEST :是指某个特定构件最新的发布版或者快照版(SNAPSHOT),最近被部署到某个特定仓库的构件。

RELEASE :是指仓库中最后的一个非快照版本。

SNAPSHOT :泛指。如果不 SNAPSHOT ,如果名字不变,本地有了不会从远程拉。如果每次更新都改名字,其他用的人也都改名字,太蛋疼了。

参考文章

https://blog.csdn.net/a303549861/article/details/93752178
https://blog.csdn.net/xzp_forever/article/details/87992971