zoukankan      html  css  js  c++  java
  • (转)Maven使用总结

    Maven使用总结

    依赖范围

    • maven创建的工程的目录中包含maintest文件夹,分别表示主程序的文件夹和测试程序的文件夹

    • maven使用scop设置依赖范围,常用的依赖范围如下:

      1. compile :编译依赖范围,在测试和运行都有效,这个是默认的依赖范围

        • 对主程序是否有效:有效
        • 对测试程序是否 有效: 有效
        • 是否参与打包:参与``
        • 是否参与部署:参与
      2. test:测试依赖的范围

        • 对主程序是否有效:无效
        • 对测试程序是否 有效: 有效
        • 是否参与打包:不参与
        • 典型的例子: junit
      3. provided

        • 对主程序是否有效: 有效
        • 对测试程序是否有效:有效
        • 是否参与打包:不参与
        • 是否参与部署:不参与
        • 典型的例子:servlet-api
          • 主要解决在开发中需要用到的,但是在部署的时候不需要的依赖,比如servlet-api,在开发中没有Tomcat运行环境,因此需要这个servlet-api,但是一旦部署在Tomcat中,Tomcat中会提供这个servlet-api,如果此时在添加的话会产生依赖冲突
      4. Runtime :测试和运行时需要。编译不需要。如JDBC驱动包

        • 对测试程序是否有效:有效
        • 对主程序是否有效:有效
        • 是否参与部署: 参与
        • 是否参与打包:参与
      5. 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这个项目,此时的HelloFriendpom.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>
    
    • 做了上面的操作,我们可以查看项目HelloFriendHello中都自动的导入了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,那么我们有如下解决办法:

      1. 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>
      
    1. 我们可以在项目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
    • 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>
    
    • 我们根据图形可以看到MakeFriendHelloFriendlog4j1.2.17的路径是2,但是到Hello中的log4j1.2.14的路径为3,因此Maven会选择HelloFriend中的log4j1.2.17版本作为MakeFriend的依赖

    pom文件中申明顺序优先

    • 路径都是一样的情况下,那么就要看在pom.xml文件中申明的顺序了,先申明的就使用哪个项目中的依赖版本

    • 假设现在的依赖改变了,MakeFriend现在是直接依赖HelloHelloFriend,如下图

    •  
      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-cleanclean这两个阶段的任务,不会执行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范围内的依赖才可以传递,但是对于testprovided中的依赖却是不可以传递的,那么必须在每个项目中都要添加依赖,此时肯定会出现每个项目中依赖版本不一致的情况,这样对于每个人的开发来说是比较困难的,因为不同版本的依赖使用的方式也不同,此时我们就需要统一管理这个版本了。
    • 下面我们以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>
    
    • 将子工程坐标和父工程坐标重复的地方删除,不删除也没关系
    • 在子工程中删除junitversion标签,表明是继承自父工程的版本,不需要指定
            <!-- 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会为我们自动的解决

    步骤

    1. 创建一个maven工程,打包方式为pom,当然也是可以直接使用父工程
    2. 在pom.xml配置文件中配置module
    3. 详细的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~
  • 相关阅读:
    Android中setContentView与inflate的区别
    Android RelativeLayout(相对布局)
    web移动开发最佳实践之js篇(转)
    SQL Server全文索引 (简单的搜索引擎)
    浅谈SQL Server中的三种物理连接操作 (转)
    sql server 优化顾问学习(转)
    IIS优化网站性能(转)
    js,css文件压缩
    SQL Server Profiler学习
    有效提高命中率的缓存设计
  • 原文地址:https://www.cnblogs.com/-X-peng/p/15306363.html
Copyright © 2011-2022 走看看