Maven基础总结

作者: 小浊微清 | 来源:发表于2017-05-03 11:47 被阅读97次

    鉴于最近基本看完《Maven实战》这本书,对于我自己的所看的结果作一下总结,理清自己的思路,并复习书中的知识。当然有时间会继续学习一下Gradle,似乎是一个更好的工具。

    我原来对于Maven的印象就是依赖管理的工具,但是在认真学习之后,认识到Maven可以实现挺多实用功能。

    • 自动化构建
    • 依赖管理(提供中央仓库,能够帮我们自动下载构建)
    • 项目信息管理

    在Maven中最重要的思维莫过于约定优于配置。虽然在Maven中没有确定的文件定义一些要求,但是大家约定的一些写法等,保证了项目的移植性,当然也可以自定义,但是不推荐(因为你写了可能就自己看得懂了,别人都看不懂)。在Maven项目中默认的主代码目录为src/test/java,默认的测试代码目录为src/test/java

    Pom文件

    在平时开发中,感觉到pom.xml文件是Maven项目中最重要的一环,它提供了项目信息与依赖管理等。

    首先,pom.xml文件中,包含一般XML文件头,指定xml文件版本以及编码方式等;接下来是project元素,包含相关的命名空间以及xsd元素等。

    <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"> <groupId>com.fei</groupId> <artifactId>fei.empty.spring.web</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <modelVersion>4.0.0</modelVersion> <properties> <jetty.port>8417</jetty.port> <spring.version>4.2.0.RELEASE</spring.version> <mybatis.version>3.3.1</mybatis.version> <slf4j.version>2.6.2</slf4j.version> <log4j2.version>2.6.2</log4j2.version> </properties> <dependencyManagement> </dependencyManagement> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> ...

    元素

    接下来重要的是groupIdartifactIdversion元素,分别表示组(当前Maven项目隶属的实际项目)、唯一ID、版本。这个是Maven的坐标元素,基本可以确定一个项目,当然这三项是必须的,不管是在项目信息还是在依赖管理中,还有packagingclassifier分别表示打包方式和帮助定义构建输出的一些附属构建( classifier是不能直接定义的,附属构建不是项目直接默认生成的,而是由附加的插件帮助生成)。例如在本例中因为是Javaweb项目,所以使用war的打包方式,在项目中如果不做声明,默认的是jar打包方式。这5个元素可以唯一的确定项目。

    版本

    关于版本,分为发布版本和快照版本,在本例中的1.0-SNAPSHOT就是快照版本,快照版本是不稳定的。在Maven中版本号的约定是<主版本>.<次版本>.<增量版本>-<里程碑版本>。关于版本管理的一些本文不会涉及。

    在配置的pom文件中提供了properties标签自定义。利用这个我们将所有的版本号集中在一起,方便更新、引用,以及减少一些版本号重复性。

    依赖

    除了在项目信息中使用到了这些元素标签,还在依赖管理中使用,这是很必要的,需要用它们去确定一个Maven项目。在 dependencies里会有许多dependency来确定每个依赖。例如spring项目中一般会包含spring-corespring-contextspring-context-support等都是Spring Framework实现依赖注入等功能必要的构建,都需要在项目中依赖。

    在依赖的servlet中定义了scop标签,表示定义依赖的范围,那么provided是什么意思呢?在一般情况中,我们有6种依赖范围:1、compile:编译依赖范围,一般在缺省默认情况下也使用这个默认范围;2、test:测试依赖范围;3、provided:已提供依赖范围,表示对于编译和测试classpath有效,但是在运行的时候无效;4、runtime:运行时依赖范围,即测试和运行classpath有效;5、system:系统依赖范围,该依赖范围与三种classpath的关系与provided相同,但是在使用这个依赖范围时,必须通过systemPath元素显式地指定依赖文件的路径,在使用时会造成不可移植性;6、import:导入依赖范围,其实是继承父模版的依赖配置,继承依赖范围。

    依赖范围(scop) 对于编译classpath有效 对于测试classpath有效 对于运行classpath有效 示例
    compile Y Y Y spring-core
    test - Y - JUnit
    provided Y Y - servlet-api
    runtime - Y Y JDBC驱动实现
    system Y Y -

    类似于java的属性继承一样,Maven也具有传递性依赖,继承依赖范围关系如下,左一列为直接依赖,横一栏为间接依赖,内容表示最终依赖范围。

    compile test provided runtime
    compile compile - - runtime
    test test - - test
    provided provided - provided provided
    runtime runtime - - runtime

    这儿其实有一些规律:在间接依赖为compile时其他两者一致;当间接依赖为test时,不具有传递性;当间接依赖为provided时,只有provided才能传递,且最终依赖为provided;当间接依赖为runtime时,一般情况时直接依赖与最终依赖一致,除了直接依赖为compile时最终依赖为runtime。

    既然有传递性依赖,以及继承等机制(这些会在后续讲到),并没有像Java一样限制只能单继承,那么必会出现像C++一样通过不同路径继承同意文件而产生冲突的情况,那么如何解决?Mave这儿需要依赖调解。第一原则是路径最近者优先;第二原则是第一声明者优先。

    当然在依赖的时候,提供了optional标签来表示可选。可选依赖是不会传递的。也提供exclusions标签来排除继承时的某些依赖,可以解决在继承时快照版本依赖的不稳定性问题。

    仓库

    在上文中讲到依赖,那么依赖后引入的包相对于其对应仓库中的路径应该是多少呢?在路径与坐标的大致对应关系为groupId/artifactId/version/artifactId-version.packaging

    对于Maven来说,仓库只分为两种:本地仓库和远程仓库。


    Maven仓库分类

    一般情况是当我们使用依赖去引入一种构建,当Maven根据坐标寻找构建时,先会去本地查找此构建,如果本地没有这个构建,去远程仓库查找,发现则下载到本地使用(当然本地构建需要查看更新时也是需要去远程仓库查找)。

    本地仓库

    一般在用户中本机中,默认情况下都有一个.m2/repository/的仓库目录。

    远程仓库

    远程仓库分为中央仓库以及自己建立的私服等。一般情况下,基本每个公司都是有自己的Maven仓库的,在开发之前的环境配置时会加上一个自己公司的setting.xml文件的配置。

    生命周期

    Maven拥有三套独立的生命周期,分别为clean、default、site。clean生命周期目标是清理项目;default是构建项目;而site生命周期目的是建立项目站点。

    clean生命周期包括pre-clean、clean、post-clean。一般调用clean时会依次执行pre-clean、clean。一般命令都是执行到指定的阶段截止。

    default是所有生命周期中最核心的部分。包括了许多阶段:calidate、initialize、generate-sources、process-sources、generate-resources、process-resources、compile、process-classes、generate-test-sources、process-test-sources、generate-test-resources、process-test-resources、test-compile、process-test-clasess、test、prepare-package、package、pre-integration-test、integration-test、post-integration-test、verify、install、deploy。在这个生命周期中可以看到有许多编译、测试等阶段。

    而site生命周期有pre-site、site、post-site、site-deploy四个阶段。

    插件

    个人觉得Maven中插件是非常重要的一环,可以帮助我们完成一些任务,并且与生命周期中的某个阶段绑定。

    ... <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>${web.port}</port> <path>/${project.artifactId}</path> <uriEncoding>UTF-8</uriEncoding> </configuration> </plugin> ...

    在这段代码中使用plugin标签加入了maven-compiler-plugin以及tomcat插件,可以使得项目可编译以及不用本地的tomcat服务器。compiler的插件是内置绑定的compile阶段,不用显式申明。当然也可以自定义绑定,在配置中加入executions、execution标签配置 执行一个任务,并用phase绑定生命周期。

    测试

    讲到插件,就不能跳过Maven的测试。测试也是使用插件来实现的,如maven-surefire-plugin插件。可以帮助我们单元测试、集成测试等。

    聚合与继承

    聚合特性能把项目的各个模块聚合在一起构建,而继承特性能帮助抽取各模块相同的依赖和插件等配置。

    所有模块组成的一个构建结构就是反应堆。单模块项目就是这个模块本身;而多模块项目则包含了各模块之间的继承和依赖关系、计算合理构建顺序。

    本文中对于许多详细知识没有作总结,只是对于常用的一些部分作了浅入的涉及。如测试、聚合与继承、以及Nexus建私服、profile、站点等知识没有解释,需要学习的可以仔细看一下《Maven实战》。

    相关文章

      网友评论

        本文标题:Maven基础总结

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