JAVA

Maven的介绍

为什么使用 Maven


说到这个问题,我们首先要看一下,如果没有 Maven,那么我们的工作是什么样子的呢?

场景一

当我们在开发过程中,当我们开发某个新功能或者修复了某个 Bug,都需要手动进行整个项目编译,运行单元测试,生成项目文档,打包,部署环境这些步骤。一旦需要重新修改代码的时候,便要将上述的操作重复一遍。机械性的重复劳动充斥着整个开发过程;

场景二

由于不同的人可能会有不同的习惯或者说是个人偏好,每当我们新建一个项目的时候,所建出来的项目可能会千奇百怪,这也给后续的维护升级带来了诸多的不便;

场景三

当项目需要依赖某个 jar 包的时候,需要到互联网上去寻找对应的 jar 包,找到 jar 包之后,将这个 jar 包添加到项目的 lib 目录下,项目组里面不同的人可能会找到不同的 jar 包,不同的 jar 包直接可能会存在冲突,这个时候,就需要去手动解决冲突;

看到这里,只想说一句,我太难了。但是,不要慌,Maven 的存在,就是为了帮助解决这些问题。

使用 Maven 之后,只需要执行一个命令就可以完成编译,运行单元测试,打包,部署的整个流程;并且 Maven 以 POM 的形式来管理 jar 包依赖;还有一点就是,使用 Maven 构建出的项目,结构统一,方便后续的维护升级。

maven 简介及优势


Maven是一个项目管理工具,可以对 Java 项目进行构建、依赖管理,是一个自动化构建工具。

maven 是一个项目构建和管理的工具,提供了帮助管理 构建、文档、报告、依赖、scms、发布、分发的方法。可以方便的编译代码、进行依赖管理、管理二进制库等等。maven 的好处在于可以将项目过程规范化、自动化、高效化以及强大的可扩展性利用 maven 自身及其插件还可以获得代码检查报告、 单元测试覆盖率、实现持续集成等等。

Maven 是专门用于构建和管理Java相关项目的工具。

Maven是意第绪语,依地语(犹太人使用的国际语),表示专家的意思。 

所以用Maven管理Java 项目,你就是专家了。

maven 优势:

  • 项目自动化编译部署
  • 项目 jar 包的依赖管理
  • 项目的插件管理

Maven的本质


是一个项目管理工具,将项目开发和管理过程抽象成一个项目对象模型

POM(Project Ojbect Model):项目对象模型

一个 maven 工程都有 pom.xml 文件,通过 pom.xml 文件定义项目的坐标、项目依赖、项目信息、插件目标等。

Maven的作用


管理jar包,通常下载一个jar包,先在本地仓库中下载,如果本地仓库中不存在,则再联网到中央仓库(镜像)去下载。

  • 增加第三方jar包(不需要自己下载jar包)
  • 管理jar包之间的依赖关系(maven自动关联下载所有依赖的jar包)

通过 maven的依赖管理对项目所依赖的 jar 包进行统一管理。

如:项目依赖 junit4.9,通过在 pom.xml 中定义 junit4.9 的依赖即使用 junit4.9,如下所示是 junit4.9的依赖定义:

将项目拆分成若干个模块:借助于Maven可以将一个项目拆分成多个工程。

Maven 主要用处:相同的项目结构

使用Maven管理的Java 项目都有着相同的项目结构

  • 有一个pom.xml 用于维护当前项目都用了哪些jar包
  • 所有的java代码都放在 src/main/java 下面
  • 所有的测试代码都放在src/test/java 下面

Maven 主要用处:统一维护jar包

如说有3个Java 项目,这些项目都不是Maven风格。那么这3个项目,就会各自维护一套jar包。 而其中有些jar包是相同的。

而Maven风格的项目,首先把所有的jar包都放在”仓库“ 里,然后哪个项目需要用到这个jar包,只需要给出jar包的名称和版本号就行了。 这样jar包就实现了共享。

如果没有Maven,你可能不得不经历下面的过程:

1 如果使用了spring,去spring的官网下载jar包;如果使用hibernate,去hibernate的官网下载Jar包;如果使用Log4j,去log4j的官网下载jar包.....
2 当某些jar包有依赖的时候,还要去下载对应的依赖jar包
3 当jar包依赖有冲突时,不得不一个一个的排查
4 执行构建时,需要使用ant写出很多重复的任务代码
5 当新人加入开发时,需要拷贝大量的jar包,然后重复进行构建
6 当进行测试时,需要一个一个的运行....检查

有了Maven,它提供了三种功能:

1 依赖的管理:仅仅通过jar包的几个属性,就能确定唯一的jar包,在指定的文件pom.xml中,只要写入这些依赖属性,就会自动下载并管理jar包。
2 项目的构建:内置很多的插件与生命周期,支持多种任务,比如校验、编译、测试、打包、部署、发布...
3 项目的知识管理:管理项目相关的其他内容,比如开发者信息,版本等等 

maven 项目约定


约定大于配置:项目约定主要是规范开发人员编程,统一项目风格,简化操作和代码量。

maven 也是这样的,约定如下图:

目录结构,其中 pom.xml 在其项目的根目录

maven 常用命令


在 cmd 中可以通过一系列的 maven 命令对我们的 maven 工程进行编译、测试、运行、打包、安装和部署。

  • compile 命令

   compile 是 maven 工程的编译命令,作用是将 src/main/java 下的文件编译为 class 文件输出到 target 目录下。

  • test 命令

   test 是 maven 工程的测试命令 mvn test,会执行 src/test/java 下的单元测试类。

  • clean 命令

   clean 是 maven 工程的清理命令,执行 clean 会删除 target 目录及内容。

  • package 命令

   package 是 maven 工程的打包命令,对于 java 工程执行 package 打成 jar 包,对于 web 工程打成 war 包。

  • install 命令

   install 是 maven 工程的安装命令,执行 install 将 maven打成 jar 包或 war 包发布到本地仓库。

Maven 指令的生命周期


maven 对项目构建过程分为三套相互独立的生命周期,它们是“相互独立”,这三套生命周期分别是:

  • Clean Lifecycle:在进行真正的构建之前进行一些清理工作。
  • Default Lifecycle:构建的核心部分,编译,测试,打包,部署等。
  • Site Lifecycle:生成项目报告,站点,发布站点。

具体如下:

清理:删除编译的结果,为重新编译做准备。

编译:java->class

测试:针对于项目中的关键点进行测试,也可用项目中的测试代码去测试开发代码

报告:将测试结果进行显示

打包:将项目中包含的多个文件压缩成一个文件,用于安装或部署(java项目打成一个jar包,web项目打成一个war包,父工程-pom)

安装:将打成的包,放到本地仓库,供其他项目使用。

部署:将打成的包,放到服务器上,准备运行。

PS:Eclipse中的项目,要在Tomcat中运行,需要部署:
  a、通过eclipse中add and remove按钮进行部署
  b、将Web项目打成一个war包,然后将该war包复制到Tomcat/webapps中即可

pom.xml 的说明


坐标定义:在 pom.xml 中定义坐标,内容包括:groupID、artifactId、version,详细内容如下: 

pom 基本配置:pom.xml 是 Maven项目的核心配置文件,位于每个工程的根目录,基本配置如下:

Maven 的版本


Maven 从发布到现在已经经历过很多个版本迭代,目前最新的版本是 2019-11-25 发布的 Maven 3.6.3 版本。

  • 1.0-2.x : 官方不再进行维护,也不建议开发者使用;
  • 3.0: Maven3.x 的第一个版本,也算是 Maven 的里程碑版本,完全向后兼容 Maven2,增加了 SLF4J 来进行日志管理,并且提高了项目构建效率和插件的扩展性;
  • 3.5.0: 该版本显著的变化是 Maven 的控制台支持不同级别日志输出不同颜色;
  • 3.6.3: 目前的最新版本,schemaLocations 地址支持 https。

Maven 的缺点


  • Maven 的整个体系相对庞大,想要完全掌握相对困难;
  • 如果项目的依赖过多,在第一次导入项目的时候需要花很长的时间来加载所需要的依赖;
  • 由于某种不可抗拒力,国内的开发者在使用 Maven 中央仓库的时候,下载速度过慢。

相同类型工具对比


在 Java 开发的世界中,有三大主流的构建工具,分别是 Ant ,Maven ,Gradle。

其中 Ant 出现的世界最早,能够提供编译、测试、打包的功能,但是 Ant 缺乏对依赖的管理,以及标准的项目结构。

后来 Maven 的出现,解决了 Ant 所不能满足的两个问题,从创建项目到构建及发布项目的整个过程定义了一套完整的规范,并且提供中央仓库,对依赖进行管理。

后来,随着 Android 的流行,近年来,以 Gradle 作为项目的构建工具也越来越流行。Gradle 在 Maven 的基础上,使用基于 Groovy 的特定领域语言(DSL)来完成配置声明,相较于 XML 来说,更加灵活。目前,Maven 和 Gradle 基本上算是平分秋色的局面,在实际的开发中,后台项目管理更倾向于使用 Maven,而在移动端开发中,Gradle 的占比更大。当然两者之间也有很多相通的地方,比如依赖管理,一致的项目结构。

Maven 本地仓储配置


如果您不配置,默认会在如下位置存放从远程下载到的包:

从中央仓库下载的jar包,都会统一存放到本地仓库中。我们需要配置本地仓库的位置。

打开maven安装目录,打开conf目录下的setting.xml文件,具体可以在网上搜索配置的方法。

你还可以在运行时指定本地仓库位置:

mvn clean install -Dmaven.repo.local=d:\yourpath

中央仓库配置


当构建一个Maven项目时,首先检查pom.xml文件以确定依赖包的下载位置,执行顺序如下:

1、从本地资源库中查找并获得依赖包,如果没有,执行第2步。
2、从Maven默认中央仓库中查找并获得依赖包(http://repo1.maven.org/maven2/),如果没有,执行第3步。
3、如果在pom.xml中定义了自定义的远程仓库,那么也会在这里的仓库中进行查找并获得依赖包,如果都没有找到,那么Maven就会抛出异常。

修改默认中央仓库地址

1.http://www.sonatype.org/nexus/  私服nexus工具使用
2.http://mvnrepository.com/ (推荐)
3.http://repo1.maven.org/maven2
4.http://maven.aliyun.com/nexus/content/groups/public/  阿里云  (强力推荐)
5.http://repo2.maven.org/maven2/ 私服nexus工具使用
6.http://uk.maven.org/maven2/
7.http://repository.jboss.org/nexus/content/groups/public
8.http://maven.oschina.net/content/groups/public/
9.http://mirrors.ibiblio.org/maven2/
10.http://maven.antelink.com/content/repositories/central/
11.http://nexus.openkoala.org/nexus/content/groups/Koala-release/
12.http://maven.tmatesoft.com/content/groups/public/

常用打包命令


mvn clean package -Dmaven.test.skip=true 
  • mvn clean package依次执行了clean、resources、compile、testResources、testCompile、test、jar(打包)等7个阶段。
  • mvn clean install依次执行了clean、resources、compile、testResources、testCompile、test、jar(打包)、install等8个阶段。
  • mvn clean deploy依次执行了clean、resources、compile、testResources、testCompile、test、jar(打包)、install、deploy等9个阶段。
    由上面的分析可知主要区别如下,
    package命令完成了项目编译、单元测试、打包功能,但没有把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库
    install命令完成了项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库,但没有布署到远程maven私服仓库
    deploy命令完成了项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库

maven跳过单元测试-maven.test.skip和skipTests的区别

-DskipTests,不执行测试用例,但编译测试用例类生成相应的class文件至target/test-classes下。
-Dmaven.test.skip=true,不执行测试用例,也不编译测试用例类。

  • 使用mvn package -Dmaven.test.skip=true,不但跳过单元测试的运行,也跳过测试代码的编译。
  • 使用 mvn package -DskipTests 跳过单元测试,但是会继续编译;如果没时间修改单元测试的bug,或者单元测试编译错误。使用上面的,不要用这个