(转)Maven使用总结
Maven使用总结
依赖范围
- 
maven创建的工程的目录中包含 main和test文件夹,分别表示主程序的文件夹和测试程序的文件夹
- 
maven使用 scop设置依赖范围,常用的依赖范围如下:- 
compile :编译依赖范围,在测试和运行都有效,这个是默认的依赖范围 - 对主程序是否有效:有效
- 对测试程序是否 有效: 有效
- 是否参与打包:参与``
- 是否参与部署:参与
 
- 
test:测试依赖的范围 - 对主程序是否有效:无效
- 对测试程序是否 有效: 有效
- 是否参与打包:不参与
- 典型的例子: junit
 
- 
provided- 对主程序是否有效: 有效
- 对测试程序是否有效:有效
- 是否参与打包:不参与
- 是否参与部署:不参与
- 典型的例子:servlet-api- 主要解决在开发中需要用到的,但是在部署的时候不需要的依赖,比如servlet-api,在开发中没有Tomcat运行环境,因此需要这个servlet-api,但是一旦部署在Tomcat中,Tomcat中会提供这个servlet-api,如果此时在添加的话会产生依赖冲突
 
- 主要解决在开发中需要用到的,但是在部署的时候不需要的依赖,比如
 
- 
Runtime:测试和运行时需要。编译不需要。如JDBC驱动包- 对测试程序是否有效:有效
- 对主程序是否有效:有效
- 是否参与部署: 参与
- 是否参与打包:参与
 
- 
system:系统依赖范围。本地依赖,不在maven中央仓库- 这个必须和systemPath结合使用,用来指定本地依赖的位置
 <!-- 添加服务提供者的jar接口 --> <dependency> <groupId>cn.tedu.dubbo</groupId> <artifactId>dubbo-provider</artifactId> <version>0.0.1</version> <scope>system</scope> <systemPath>${basedir}/src/main/webapp/WEB-INF/lib/dubbo-provider-helloService-0.0.1.jar</systemPath> </dependency>
- 这个必须和
 
- 
依赖传递
- 在开发项目的时候,我们通常需要建立多个项目,如果一个项目中需要用到另外一个项目的类或者数据,那么需要引入这个项目快照
- 如果HelloFriend项目依赖Hello这个项目,此时的HelloFriend的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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>cn.tedu</groupId>
    <artifactId>HelloFriend</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    
    <dependencies>
        <!-- 添加Hello这个项目的依赖快照 -->
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>Hello</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
    
</project>
- 此时项目HelloFriend中存在依赖只有Hello项目这个jar,但是如果我们在Hello项目的pom.xml文件中添加一个junit的依赖,这个依赖范围为设置为compile,如下:
<dependencies>
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
  </dependencies>
- 做了上面的操作,我们可以查看项目HelloFriend和Hello中都自动的导入了Junit依赖,这个就是依赖传递。
注意
- 依赖传递只有是依赖范围为compile的情况下才有作用,如果我们需要一个servlet-api的依赖,因为servlet-api这个jar在部署的时候会和Tomcat冲突,因此只能设置为provided,但是此时就不能依赖传递了,只能在每个项目中的pom.xml文件中都添加了
依赖排除
- HelloFriend项目依赖- Hello项目,其中- compile范围的依赖都会导入- HelloFriend中
- 使用dubbo默认会添加给我们添加spring-framework的版本为2.5.6,默认添加的依赖只能排除,不能在项目中再添加一个其他的版本,只有排除之后才能添加,否则会导致jar包冲突
- Hello项目中的依赖为:
    <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
        <!-- 添加dubbo依赖的jar,会自动添加spring 2.5版本的依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
        </dependency>
- 
此时 HelloFriend的项目需要使用4.3.13版本的spring,那么我们有如下解决办法:- 在Hello项目中改变依赖,排除spring2.5版本的:- 一般在公司中项目的版本都是定制好的,我们不可能随意改动父项目中定义好的版本,因此这个方法明显是不行的
 
 <!-- 使用spring4.3.13 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.13.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> <!--排除spring2.5版本--> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> </exclusions> </dependency>
- 在
- 我们可以在项目HelloFriend排除这个spring的依赖,那么我们就可以不需要改变Hello项目中的依赖了,如下:- 这个才是正确的排除依赖的方式
 
        <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.13.RELEASE</version>
        </dependency>
        
        <!-- 添加Hello这个项目的依赖快照 -->
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>Hello</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <!--排除项目中的spring2.5的依赖,这个不会影响Hello项目中的版本-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
            </exclusions>
        </dependency>       
依赖原则
依赖路径最短优先原则
- 假设项目MakeFriend依赖HelloFriend,并且HelloFriend依赖Hello项目。此时Hello项目中使用的log4j 1.2.14版本的,但是在HelloFriend版本中使用的是log4j1.2.17版本的,那么此时的MakeFriend应该选择什么版本呢?
- 
![]() image image
- Hello的依赖如下:
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.14</version>
        </dependency>   
- HelloFriend依赖如下:
    <!-- 添加Hello这个项目的依赖快照 -->
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>Hello</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        
        <!--添加1.2.17版本的log4j-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
- MakeFriend的依赖如下:
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>HelloFriend</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
- 我们根据图形可以看到MakeFriend到HelloFriend的log4j1.2.17的路径是2,但是到Hello中的log4j1.2.14的路径为3,因此Maven会选择HelloFriend中的log4j1.2.17版本作为MakeFriend的依赖
pom文件中申明顺序优先
- 
在 路径都是一样的情况下,那么就要看在pom.xml文件中申明的顺序了,先申明的就使用哪个项目中的依赖版本
- 
假设现在的依赖改变了, MakeFriend现在是直接依赖Hello和HelloFriend,如下图
- 
![]() image image
- 
我们可以看出此时到两个版本的依赖都是一样的路径为 2,那么我们应该选择哪个版本呢,此时就需要看看在MakeFriend中的pom.xml文件的申明顺序- 可以看出先申明的是HelloFriend,因此MakeFriend使用的是log4j1.2.17
 
- 可以看出先申明的是
<!-- 先申明HelloFriend,那么就要使用log4j.1.2.17版本 -->
        <dependency>    
            <groupId>cn.tedu</groupId>
            <artifactId>HelloFriend</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>Hello</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
覆写优先
生命周期
- maven的生命周期有三个部分组成,分别为clean生命周期,site生命周期,default生命周期
生命周期调用的特点
- 三大生命周期中也会包含各个阶段,并且各个阶段是有序进行的,maven为了实现构建的自动化,如果我们使用了命令调用生命周期后面的处理阶段,那么会从最前面的阶段开始执行,不用每一个阶段都执行一遍。
clean生命周期
- 
在进行真正的构建之前进行一些清理工作 
- 
clean生命周期包括: - per-clean:执行了一些需要在clean之前完成的工作
- clean:移除所有上一次构建生成的文件
- post-clean:执行一些需要在clean之后立刻完成的工作
 
- 
当我们执行 mvn:clean命令的时候只会执行per-clean和clean这两个阶段的任务,不会执行post-clean的工作
default生命周期
- 构建的核心部分,编译、测试、打包、部署
- 包括如下的23个生命周期阶段:
| 生命周期阶段 | 描述 | 
|---|---|
| validate | 检查工程配置是否正确,完成构建过程的所有必要信息是否能够获取到。 | 
| initialize | 初始化构建状态,例如设置属性。 | 
| generate-sources | 生成编译阶段需要包含的任何源码文件。 | 
| process-sources | 处理源代码,例如,过滤任何值(filter any value)。 | 
| generate-resources | 生成工程包中需要包含的资源文件。 | 
| process-resources | 拷贝和处理资源文件到目的目录中,为打包阶段做准备。 | 
| compile | 编译工程源码。 | 
| process-classes | 处理编译生成的文件,例如 Java Class 字节码的加强和优化。 | 
| generate-test-sources | 生成编译阶段需要包含的任何测试源代码。 | 
| process-test-sources | 处理测试源代码,例如,过滤任何值(filter any values)。 | 
| test-compile | 编译测试源代码到测试目的目录。 | 
| process-test-classes | 处理测试代码文件编译后生成的文件。 | 
| test | 使用适当的单元测试框架(例如JUnit)运行测试。 | 
| prepare-package | 在真正打包之前,为准备打包执行任何必要的操作。 | 
| package | 获取编译后的代码,并按照可发布的格式进行打包,例如 JAR、WAR 或者 EAR 文件。 | 
| pre-integration-test | 在集成测试执行之前,执行所需的操作。例如,设置所需的环境变量。 | 
| integration-test | 处理和部署必须的工程包到集成测试能够运行的环境中。 | 
| post-integration-test | 在集成测试被执行后执行必要的操作。例如,清理环境。 | 
| verify | 运行检查操作来验证工程包是有效的,并满足质量要求。 | 
| install | 安装工程包到本地仓库中,该仓库可以作为本地其他工程的依赖。 | 
| deploy | 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程。 | 
- 当一个阶段通过 Maven 命令调用时,例如mvn compile,只有该阶段之前以及包括该阶段在内的所有阶段会被执行。
- [图片上传失败...(image-7b5809-1538922827484)]
Site生命周期
- Maven Site 插件一般用来创建新的报告文档、部署站点等。
- 包含以下阶段
- pre-site:执行一些需要在生成站点文档之前完成的工作
- site:生成项目的站点文档
- post-site:执行一些需要生成站点文档之后完成的工作
- site-deploy:将生成站点文档部署到特定的服务器上
 
Maven统一管理依赖的版本号
- 假设如下的依赖:
    <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.13.RELEASE</version>
        </dependency>
        <!-- Spring-JDBC,要和spring-webmvc的版本一致 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.3.13.RELEASE</version>
        </dependency>   
- 那么当我们需要改变spring的依赖版本号为4.3.12.RELEASE,那么我们只有逐个改变version中的值,现在是两个依赖比较好改变的,如果要有很多个的话,那么难免会改错,因此我们需要使用一种方式统一管理依赖的版本号。我们可以使用<properties>标签来管理,新的配置文件如下:- properties中的标签体可以任意指定,如果需要引用定义的标签体中的内容,那么直接使用- ${标签体}即可
- 此时我们要是改变版本,那么只需要改变<properties>中的版本即可
 
<!-- 使用properties管理版本号 -->
    <properties>
        <!-- 这里的标签体可以任意指定,后续只要使用${}引用标签体即可使用其中定义的内容 -->
        <spring-version>4.3.13.RELEASE</spring-version>
    </properties>
    
    <dependencies>
        <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <!-- version使用${} -->
            <version>${spring-version}</version>
        </dependency>
        <!-- Spring-JDBC,要和spring-webmvc的版本一致 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring-version}</version>
        </dependency>
        
    </dependencies>
继承
- 我们知道只有compile范围内的依赖才可以传递,但是对于test和provided中的依赖却是不可以传递的,那么必须在每个项目中都要添加依赖,此时肯定会出现每个项目中依赖版本不一致的情况,这样对于每个人的开发来说是比较困难的,因为不同版本的依赖使用的方式也不同,此时我们就需要统一管理这个版本了。
- 下面我们以junit的版本控制为例
步骤
- 创建一个父工程Hello-Parent,打包的方式为pom
- 在Hello-Parent中的pom.xml文件中使用dependencyManagement管理版本,控制junit的版本依赖
<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.0</modelVersion>
  <groupId>cn.tedu</groupId>
  <artifactId>Hello-Parent</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
    
  <!-- 使用properties控制版本号 -->
  <properties>
    <junit-version>4.12</junit-version>
  </properties>
  
  <!-- 使用dependencyManagement管理版本 -->
  <dependencyManagement>
    
    <dependencies>
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit-version}</version>
            <scope>test</scope>
        </dependency>
        
    </dependencies>
  </dependencyManagement>
  
</project>
- 在子工程中使用parent标签指定声明对父工程的引用
    <parent>
        <groupId>cn.tedu</groupId>
        <artifactId>Hello-Parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <!-- 使用relativePath指定父工程的相对位置 -->
        <relativePath>../Hello-Parent</relativePath>
    </parent>
- 将子工程坐标和父工程坐标重复的地方删除,不删除也没关系
- 在子工程中删除junit的version标签,表明是继承自父工程的版本,不需要指定
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <!--此时不需要指定version了,因为父工程中已经指定了-->
        </dependency>
- 子工程全部的配置
<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.0</modelVersion>
    <!-- 这里的groupId和父工程中的重复了,因此可以删除 
    <groupId>cn.tedu</groupId>-->
    <artifactId>Hello</artifactId>
    <!-- 这里的version版本也和父工程的重复了,因此可以删除
    <version>0.0.1-SNAPSHOT</version> -->
    
    <parent>
        <groupId>cn.tedu</groupId>
        <artifactId>Hello-Parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <!-- 使用relativePath指定父工程的相对位置 -->
        <relativePath>../Hello-Parent</relativePath>
    </parent>
    
    <dependencies>
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <!--不需要指定version-->
        </dependency>
    </dependencies>
</project>
聚合
- 我们在开发项目的时候都是分模块开发的,此时如果想要使用maven安装这个项目的话,那么需要一个一个的安装,但是我们可以使用聚合的方式,可以实现一次性安装。并且安装还是有先后顺序的,一定要先安装父工程,否则将会找不到依赖信息,我们使用聚合的方式就没有先后安装的障碍了,maven会为我们自动的解决
步骤
- 创建一个maven工程,打包方式为pom,当然也是可以直接使用父工程
- 在pom.xml配置文件中配置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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>cn.tedu</groupId>
  <artifactId>Hello-Manager</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  
  <!-- 继承父工程 -->
  <parent>
        <groupId>cn.tedu</groupId>
        <artifactId>Hello-Parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <!-- 使用relativePath指定父工程的相对位置 -->
        <relativePath>../Hello-Parent</relativePath>
    </parent>
  
  <!-- 使用聚合的方式 -->
  <modules>
    <module>../Hello-Parent</module>
    <module>../Hello</module>
    <module>../HelloFriend</module>
    <module>../MakeFriend</module>
  </modules>
  
</project>原文:https://www.jianshu.com/p/b7d08690d242
    Keep moving forwards~
 
                    
                     
                    
                 
                    
                


 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号