Maven小结

作者: Arvesynden | 来源:发表于2019-10-02 22:28 被阅读0次

    什么是Maven?

    Maven是一个项目管理和综合工具,Maven使用标准的目录结构和默认构建生命周期。提供了开发人员构建一个完整的生命周期框架,开发团队可以自动完成该项目的基础设施建设。

    简单来说,Maven能简化和标准化项目建设过程。

    Maven项目的结构和内容是在一个XML文件中声明,pom.xml的项目对象模型(POM),这是整个Maven系统的基本单元。

    Maven的作用:

    1、下载jar包:只要添加相应配置,会自动下载相应jar包。

    2、下载依赖:只要配置的jar包所依赖的其他jar包都会被maven自动下载下来

    3、热部署:在web项目已经运行的时候,修改代码的能直接被web服务器所接受,就不需要重启服务器了,或者重新部署代码,而且可以直接通过maven 打包war或者jar项目。

    Maven目录结构:

    src/main:存放主程序

    src/main/java:存放java源代码

    src/main/resources::存放框架或其他工具的配置文件

    src/test/java:存放测试程序

    src/test/resources:存放测试的配置文件

    target:执行 maven install命令时自动生成的。

    pom.xml:Maven的核心配置文件

    Maven环境配置

    Maven如何管理jar包

    什么是坐标?

    ①、数学中的坐标

        在平面上,使用 X 、Y 两个向量可以唯一的定位平面中的任何一个点

        在空间中,使用 X、Y、Z 三个向量可以唯一的定位空间中的任意一个点

    ②、Maven 中的坐标

        俗称 gav:使用下面三个向量子仓库中唯一定位一个 Maven 工程

        在项目中的 pom.xml 文件中,我们可以看到下面gav的定义:

                  1、groupid:公司或组织域名倒序 

          <groupid>com.ys.maven</groupid>

        2、artifactid:模块名,也是实际项目的名称

          <artifactid>Maven_05</artifactid>

        3、version:当前项目的版本

          <version>0.0.1-SNAPSHOT</version>

    ③、Maven 坐标和仓库,jar 包的关系

    1、仓库       

            maven项目使用任何一个构件的方式都是完全相同的,maven可以在某个位置统一存储所有maven共享的构件,这个统一的位置便是仓库。仓库是Maven 用来存放 jar 包的地方。

           仓库只分为两类:本地仓库和远程仓库。当maven根据坐标寻找构件的时候,它首先会查看本地仓库,如果本地仓库存在,直接使用;如果本地仓库不存在,需要查看是否有更新的构件版本,maven就会去远程仓库寻找,发现需要的构件之后,下载到本地仓库再使用。如果都没有找到,maven会报错。

    2、关系

          可简单理解为:maven通过坐标从仓库中寻找构件(即依赖的jar包)。

    Maven生命周期

    完整的项目构建过程包括:清理——>编译——>测试——>打包——>集成测试——>验证——>部署。

    maven中定义三套独立的生命周期:分别包括clean、default、site,这三套生命周期是相互独立的,每个生命周期又包含一些阶段,各个生命周期的阶段是有顺序的,且后面的阶段依赖前面的阶段,执行每个阶段时,其前面的阶段会依次顺序执行,但不会触发另外两套生命周期的任何阶段。

    1、clean:目的是来清理项目,它又分为三个阶段。

    pre-clean执行清理前的工作

    clean清理上一次构建生成的所有文件

    post-clean执行清理后的文件

    2、default:目的是来构建项目(生命周期中最核心,包含了构建项目时所要执行的步骤),阶段比较多,常用阶段有以下几种。

    例如:compile test package install,默认都是default这个生命周期中的。

    3、site:生成项目的站点,会根据pom种的信息,自动生成一个站,它又分为以下几个阶段。

    pre-site:在生成项目站点前要完成的工作。

    site:生成项目的站点文档。

    post-site:在生成项目站点后要完成的工作。

    site-deploy:发布生成的站点到服务器上。

           在maven中,只要在同一个生命周期,你执行后面的阶段,那么前面的阶段也会被执行,而且不需要额外去输入前面的阶段。如,mvn package;在运行package命令之前,并没有compile和test,但当我们运行package之后,它的compile和test是依次执行的,也就是运行package这个阶段时,compile和test会自动的运行。

    什么是依赖?

    每当我们需要使用某个框架时,比如 SpringMVC,那么我们需要导入相应的 jar 包,但是手动导入包的时候,往往会漏掉几个 jar 包,那么在使用该框架的时候系统就会报错。那么我们就说导入的包与未导入的包存在依赖关系。而使用 Maven,我们只需要在 pom.xml文件中进行相应的配置,它就会帮助我们自动管理 jar 包之间的依赖关系。

    以 Junit 为例,在 pom.xml 文件中进行详细而完整的配置。

    <project>     

        <dependencies>

            <dependency>

                <groupId>junit</groupId>     

                <artifactId>junit</artifactId>     

                <version>3.8.1</version>

                <type>...</type>

                <scope>...</scope>

                <optional>...</optional>

                <exclusions>     

                    <exclusion>     

                      <groupId>...</groupId>     

                      <artifactId>...</artifactId>     

                    </exclusion>

              </exclusions>     

            </dependency>        

          </dependencies>     

    </project>

         ①、dependencies:一个 pom.xml 文件中只能存在一个这样的标签。用来管理依赖的总标签。

      ②、dependency:包含在dependencies标签中,可以有无数个,每一个表示一个依赖

      ③、groupId,artifactId和version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven根据坐标才能找到需要的依赖。

      ④、type:依赖的类型,对应于项目坐标定义的packaging。大部分情况下,该元素不必声明,其默认值是jar。

      ⑤、scope:依赖的范围,默认值是 compile。

      ⑥、optional:标记依赖是否可选。

      ⑦、exclusions:用来排除传递性依赖。

    依赖的范围Scope

     <scope>...</scope>标签的可选配置:compile、test、provided、runtime、system、import

    1)编译依赖范围(compile),该范围就是默认依赖范围,此依赖范围对于编译、测试、运行三种classpath都有效,如log4j。

    2)测试依赖范围(test),顾名思义就是针对于测试的,使用此依赖范围的依赖,只对测试classpath有效,在编译主代码和项目运行时,都将无法使用该依赖,最典型的例子就是 Junit。

    3)已提供依赖范围(provided),使用该依赖范围的maven依赖,只对编译和测试的classpath有效,对运行的classpath无效,典型的例子就是servlet-api。

    4)运行时依赖范围(runtime),使用该依赖范围的maven依赖,只对测试和运行的classpath有效,对编译的classpath无效,典型例子就是JDBC的驱动实现。

    5)系统依赖范围(system),该依赖与classpath的关系与 provided依赖范围完全一致,但是系统依赖范围必须通过配置systemPath元素来显示指定依赖文件的路径,此类依赖不是由maven仓库解析的,而且往往与本机系统绑定,可能造成构件的不可移植,因此谨慎使用,systemPath元素可以引用环境变量。

    6)导入依赖范围(import),该依赖范围不会对三种classpath产生影响,该依赖范围只能与dependencyManagement元素配合使用,其功能为将目标pom文件中dependencyManagement的配置导入合并到当前pom的dependencyManagement中。

    依赖传递

    举例:古惑仔电影中,山鸡和南哥混,南哥和B哥混,对于山鸡而言就间接和B哥混了,换成程序而言,山鸡依赖南哥,南哥依赖B哥,山鸡就就依赖传递B哥了。

    案例:

    描述:新建3个maven项目,选择quickstart模板,第一个Group Id为com.hongxing,Artifact Id为hongxing-bge,Package为默认的,第二个Group Id为com.hongxing,Artifact Id为hongxing-nange,第三个Group Id为com.hongxing,Artifact Id为hongxing-shanji。

    步骤1:南哥依赖于B哥,南哥的pom.xml中进行配置,引入B哥的依赖,需要知道B哥的坐标,然后编译一下南哥,Maven——>Maven build(在Goals:compile)。

    南哥的maven项目首先会到本地仓库中进行查找B哥的jar包,如果本地仓库中没有,则会从远程中央仓库中下载,如果远程中央仓库中没有,则会报错,我们先将B哥进行打包,Maven——>Maven build(Goals:clean package),然后再将B哥安装到本地仓库中Maven——>Maven build(install),它依然会编译,并且会测试一遍,并且安装到指定的仓库中,接下来再对南哥进行编译Maven——>Maven build(clean compile),这样南哥就构建成功了。

    步骤2:山鸡依赖于南哥,首先,要打包南哥的maven项目,并进行安装到本地仓库中Maven——>Maven build(clean install),依旧要找到南哥的坐标,然后编译一下山鸡Maven——>Maven build(compile)

    依赖具有传递性,山鸡的maven项目并没有依赖B哥,B哥的依赖缺自动的加入到了山鸡的依赖目录里。

    排除依赖:依赖南哥的<dependency>标签中添加<exclusions><exclusion>B哥的坐标<exclusions><exclusion>

    举例:山鸡只听从南哥的吩咐,不听其他人的吩咐,将B哥的依赖从山鸡的maven项目依赖中排除。

    依赖冲突

    如果有A(南哥)和B(B哥)依赖了一个不同版本相同的构件(commons-io),那么对于依赖于AB的C(山鸡哥)来说,它究竟依赖于A和B的哪一个版本的构件,这里有两条原则。

    1.短路优先

       A->B->C->X(jar)

       A->D->X(jar) (优先用这个X)

    2.先申明先优先

    如果路径长度相同,则谁先声明,先解析谁

    maven聚合和继承

    maven聚合:如果想在maven中将多个项目进行install,将其安装到本地仓库中,必须对其依次执行install命令,maven中有一种方式可以将其放到一起运行,这种方式称为聚合。

    案例:将山鸡、南哥、B哥聚合到本地仓库中,这里需要新建一个maven项目,依旧使用quickstart模板,Group Id为com.hongxing,Artifact Id为hongxing-aggreation,它作为其他pom的容器,需要修改它的pom的<package>为pom</package>,然后使用<modules><module>B哥的maven项目名</module><module>南哥的maven项目名</module><module>山鸡的maven项目名</module></modules>,然后右键hongxing-aggreation的Maven——>Maven build,Goals输入clean install控制台输出结果为三次构建,第一次生成B哥的jar,并且将其安装到本地仓库中,第二次生成南哥的jar,并且将其安装到本地仓库中,第三次生成山鸡的jar,并且将其安装到本地仓库中。

    继承:三个maven项目中都有一个共同的特点,就是都使用了junit,并且在每个项目的pom.xml中,都对其进行了配置,比如说b哥的maven使用了如下图,这样就出现了很多重复的地方,其实maven中可以想java中一样,将其共同的特性封装成一个父类,所以新建一个maven项目,Group Id为com.hongxing,Artifact Id为hongxing-parent,然后修改它的pom.xml,要将标签放置在标签里,如果使用这个标签对依赖进行管理,它并不会在这个项目中运行,也可以将junit的版本号提取出来,在外面定义一个属性,并在该属性里通过设置junit的版本号,这样就可以在中的中像使用EL表达式那样来调用它,${junit.version},最后将它的改成pom,然后打开B哥的pom让其继承pom,这里就可以将junit的版本号进行删除,也可以删除掉,这里要使用到标签,然后引入我们的parent的maven的坐标,这样junit已经从父类parent,也就是pom中继承过来了。

    Maven创建web项目

    Maven创建web项目

    Maven VS Ant

    相同点:

               都是项目构建管理工具。

    不同点有:

               1. Maven约定了目录结构,而Ant没有。

               2. Maven是声明式的,用pom.xml文件;而Ant是程序式的,构建过程需要自定义,用builder.xml.

               3. Maven是有生命周期的,而Ant没有。

               4. Maven内置依赖管理和Repository来实现依赖的管理和统一存储;而Ant没有。Maven第一次install的时候会把依赖的jar包和构件从远处库(又叫中央库,http://repol.maven.org/maven2,统一存储maven可以解释的文件资源)下载到本地库(先从本地仓库找)。Maven还可以管理传递依赖。

               5.Maven配置比较简单,有很多的约定、规范、标准,可以用较少的代码干更多的事;而Ant配置比较麻烦,需要配置整个构建的过程(但Ant配置灵活)。

    相关文章

      网友评论

        本文标题:Maven小结

        本文链接:https://www.haomeiwen.com/subject/fbchpctx.html