zoukankan      html  css  js  c++  java
  • Maven初步

    Maven初入

    maven 是一个项目管理工具, 它包含了一个 项目对象模型(Project Object Model POM), 一组标准集合, 一个项目生命周期(Project Lifecycle), 一个依赖管理系统(Dependency Management System), 和用来运行 定义在 生命周期阶段中插件目标的逻辑.

    Maven的核心只做一些基础的事情, 解析XML文档, 管理生命周期, 插件, 仅此而已; Maven的主要职责是委派给各种各样的插件, 如编译源码, 打包二进制代码, 发布站点 和 其他构建任务, 而插件从 maven仓库获得.

    文档参考自: Maven权威指南

    Maven初步

    安装自不必赘述, Maven的相关配置在 ~/.m2/settings.xml,

    ~/.m2/repository 是本地仓库目录.

    maven核心概念

    1. 插件和目标

      就像在前面所提到过的, Maven的核心所做的工作很少, 大部分工作都会叫给插件来做, 一个插件 是一个或多个目标的集合, 插件的直观表现就是一个或多个jar包, 目标指的就是 某一个具体的方法, 可以配置相应的参数, 同时需要给定一部分必须参数;

      简写: pluginId:goalId

    2. 生命周期(Lifecycle)

      生命周期是包含在一个项目中一系列有序的阶段, 在maven中配有默认的生命周期, 以验证项目的基本完整性开始, 以把项目发布成产品结束.

      其中, 插件目标是可以附着在生命周期上的, 会随着生命周期的阶段 一步步执行, 当 maven执行一个阶段的时候, 他首先会有序执行前面的所有阶段, 并执行绑定在阶段上的默认目标, 到命令指定的那个阶段为止;

      recourses: recourses; Recourses插件的 recourses目标绑定在了 recourses阶段, 这个目标复制 src/main/recourses 下的所有资源 和 其他任何配置的资源目录, 到输出目录;

      compiler: compile 绑定到了 compile阶段,编译 src/main/java 下的所有源代码 和 其他任何配置的资源目录, 到输出目录.

      recourses: testRecourses Resources插件的 testRecourses目标绑定到了 test-recourses阶段, 对应 src/test/resources

      compiler: testCompile 对应 src/test/java

      surefire: test surefire插件的目标test 绑定到 test阶段, 这个目标运行所有的测试, 并创建那些 捕捉 详细测试结果的文件, 默认情况下, 如果有测试失败, 这个目标会终止

      jar:jar 绑定到 package阶段, 把输出目录打包成 jar文件.

    3. Maven 坐标

      POM为项目命名, 提供了项目的一组唯一标识符(坐标), 并通过 依赖(dependencies), 父(parents) 和 先决条件(prerequisite) 来定义和其他项目的关系.

      Maven定义了一组坐标, 他们可以用来标识一个项目, 一个依赖, 或者MavenPom里一个插件.

      GroupId: 团体, 公司, 组织等其他, 就是java中的 com.company.project

      artifactId: 项目标识

      version: 版本号, 一般会通过加上 "SNAPSHOT"标记, 标识正在开发中.

      packing(非必须): 默认为 jar, 项目打包后输出, war 表示web 项目.

      同时需要注意的是: 在 artifactId中最好不要使用 "."

    4. Maven仓库

      路径为, 相对于仓库根目录:

      /<groupId>/<artifactId>/<version>/<artifactId>-<version>.<packing>

    5. Maven依赖

      对于依赖, 目前只需要知道依赖具有传递性,即可.

    Maven注意事项

    1. 优化, 降低依赖重复

      1. 上移共同的依赖至 dependencyManagement

        如果多于一个项目依赖于一个特定的依赖, 就可以在 dependencyManagement中列出这个依赖, 父POM包含一个版本和一组排除配置, 在子POM中需要使用 groupId和artifactId引用这个依赖, 如果依赖已经在 dependencyManagement中列出, 子项目可以额忽略版本和排除配置;

         <properties>
             <hibernate.annotation.version>3.3.0</hibernate.annotation.version>
         </properties>
        

        通过这种方式将版本信息定义为 常量, 通过 ${ }引用变量

         <dependency>
             <groupId>org.hibernate</groupId>
             <artifactId>hibernate-annotation</artifactId>
             <version>${hibernate.hibernate.annotation.version}</version>
         </dependency>
        
      2. 为兄弟项目使用内置的 version 和 groupId

      3. 使用相同的 groupId 和 ${project.version}.

      4. 上移共同的 plugin 至 pluginManagement

      5. 显示的声明依赖, 不要通过依赖传递性来引用 jar包

      6. 使用 Maven Denpendency插件优化:

        通过 mvn dependency:analyze 对项目进行分析, 但增删依赖判断的先决条件是单元测试;

        在 analyze中, 生命周期依次为:
        recourses, compile, testRecourses, testCompile, analyze;

        会将执行中的错误, 未声明的 jar, 声明未使用的jar 种种体现出来.

        而使用 mvn dependency:tree , 会列出项目中所有的直接和传递性依赖.

      7. 几个帮助插件

        mvn help:active-profiles 列出当前构建中活动的 Profile

        mvn help:effective-pom 显示当前构建的实际 pom

        mvn help:effective-settings 打印实际的setting, 包含全局和用户级别的

        mvn help:describe 描述插件的属性, 无需在项目目录下运行, 但必须提供插件的 groupId 和 artifactId

        如: mvn help:describe -Dplugin=complier [Dmojo=compile] [-Dfull]

        第二个参数表示插件中的某一个目标, 第三个参数为目标的所有信息, 同时在:

        "-D<name>=<value>" 这种方式设定 调用 mvn 插件目标 ,传入目标中的参数中的 值. 需要注意的是, 这并非是 Maven的语法, 其实是 java 用来设置系统属性的方式.

    Maven Pom

    所有的 Maven POM 都继承自超级POM, 超级POM所处目录为: {Maven HOME}/lib/maven-model-builder-{Maven Version}.jar 内 org.apache.maven.model 下的 POM-4.0.0.xml.

    文件主要定义了:

    1. 单独的远程仓库, https://repo.maven.apache.org/maven2

       <repositories>
       <repository>
       <id>central</id>
       <name>Central Repository</name>
       <url>https://repo.maven.apache.org/maven2</url>
       <layout>default</layout>
       <snapshots>
           <enabled>false</enabled>
       </snapshots>
       </repository>
       </repositories>
      
    2. 为核心插件提供了默认的版本

    我们自己建立的 POM最顶层继承自 超级 POM, 其次是所有的 父级POM, 自上向下 会一层层 覆盖之前的默认配置, 通过 mvn help:effective 可以查看当前项目的有效pom.

    下面就开始一步步看POM.xml文件中的配置:

    1. version

       <major version>.<minor version>.<incremental version>-<qualifier>
      
       1.3.5-beta-01
      

      其中1为主版本号, 3为次版本号, 5为增量版本号, beta-01为限定版本号(alpha 和 beta). 如果版本号符合规则要求, 则按照版本号来比较, 否则按照字符串规则来进行比较. 比如 a10 是 排在 a2前面的, 因此 a10属于旧版本, 但在我们的定义中, 却应该是相反的.

      版本界限配置方式:

      (loVersion, hiVersion) 不包含
      [loVersion, hiVersion] 包含

       <version>[3.8, 4.1.2]</version>
      

      当不指定上界/下界时, 则为以上/以下

      SNAPSHOT

      如果你在版本中使用了 字符串 SNAPSHOT, 表示项目正处于 活动的 开发状态, Maven会在安装 或部署的时候将 符号展开为 一个时间和日期,转换为 UTC.(也就是快照版本)

      如在创建的时候, 默认为 0.1-SNAPSHOT, 而后将项目部署到了 Maven仓库, Maven会将版本展开为 0.1-YYYYMMDD-HH24MISS-1, 这里的时间 为UTC时间.

      如果项目依赖的一个组件正处于开发过程中, 依赖它的 SNAPSHOT版本, 则在运行构建的时候, 会自动从仓库下载最新的 SNAPSHOT, 同时, 要依赖 SNAPSHOT版本, 用户必须在 POM中使用 repository 和 pluginRepository 开启下载 SNAPSHOT功能.

       <!--选择对应的 坐标, 将 enabled 属性设置为 true 即可-->
       <repositories>
           <repository>
           <id>central</id>
           <name>Central Repository</name>
           <url>https://repo.maven.apache.org/maven2</url>
           <snapshots>
               <enabled>true</enabled>
           </snapshots>
           </repository>
       </repositories>
      
       <pluginRepositories>
           <pluginRepository>
           <id>central</id>
           <name>Central Repository</name>
           <url>https://repo.maven.apache.org/maven2</url>
           <snapshots>
               <enabled>true</enabled>
           </snapshots>
           </pluginRepository>
       </pluginRepositories>
      

      而发布到 非 snapshot的 Maven仓库的构建不能依赖于 SNAPSHOT版本, 仅用于开发过程.

      LATEST 和 RELEASE

      当依赖于一个插件 或 依赖, 可以使用特殊值:

      LATEST: 最新发布的版本 或 快照版.

      RELEASE: 仓库中 最后一个非快照版本.

      在项目发布的时候, 尽量不要使用 这三个关键字, 仅在开发时使用

    2. 变量引用

      在Maven中有三个内置隐士变量:

      env: 表示 environment, 系统的环境变量, 如 ${env.PATH}, 需要注意的是需要大写, 如 ${env.JAVA_HOME}

      settings: 这个指的是 settings.xml中的属性, 但一直引用不成功.

      project: 引用当前 project中的属性 如 ${project.artifactId}.

      ${basedir}, 可以访问当前项目根目录

      Java系统属性

      凡是可以被 java.lang.System 中的 getProperties()方法访问的属性

      可以在Java中通过 System.getProperties().list(System.out); 在Maven中通过 ${} 直接访问, 如 ${java.runtime.name}

      自定义属性:

       <properties>
           <attribute>value</attribute>
       </properties>
      

      访问方式即: ${attribute.value}

    3. 依赖范围

       <version>1.0</version>
       <scope>test</scope>
      

      compile: 编译范围, 默认范围, 在所有的classpath都可以使用, 也会被打包

      provided: 已提供范围, 只有当 JDK/容器已经提供该依赖之后才使用, 如在 开发中 需要 Servlet API编译一个 Servlet, 但在打包发布之后这部分应该由 容器/服务器本身来提供. 仅在编译时可用. 不可传递, 不会打包.

      runtime: 运行时范围, 在编译时不需要, 在运行时需要.

      test: 测试范围, 仅在测试时需要, 测试运行, 测试编译.

      system: 系统范围, 必须提供 systemPath, 即本地jar文件的路径.

      可选依赖:

       <version>1.0</version>
       <optional>true</optional>
      

      通过这种方式生命的依赖, 不会被传递. 需要在子项目中再度生命

    4. 依赖的传递

      test范围不会被传递, provided范围 仅在 provided中被传递, runtime 和 compile 在 四种范围都会被传递.

      e.g. : A 包含对 B的测试范围依赖, B 包含对 C的编译时依赖, 则 C为A的测试范围依赖

       A:
       <dependency>
           <groupId>B</groupId>
           <artifactId>B</artifactId>
           <version>1.0</version>
           <scope>test</scope>
       </dependency>
       B:
       <dependency>
           <groupId>C</groupId>
           <artifactId>C</artifactId>
           <version>1.0</version>
       </dependency>
      

      e.g. : A包含对 B的测试范围依赖, B包含对C的测试范围依赖, 则 A与C无关.

       A:
       <dependency>
           <groupId>B</groupId>
           <artifactId>B</artifactId>
           <version>1.0</version>
           <scope>test</scope>
       </dependency>
       B:
       <dependency>
           <groupId>C</groupId>
           <artifactId>C</artifactId>
           <version>1.0</version>
           <scope>test</scope>
       </dependency>
      

      依赖追踪:

      在 Maven中, 如果多个项目依赖于同一个 project, 则Maven会找到 所有依赖中版本最新的 依赖, 作为最终的选择, 所以可以排除对应的依赖, 且同时 可以 更换自己想要的版本.

      e.g.:

       <dependency>
           <groupId>B</groupId>
           <artifactId>B</artifactId>
           <version>1.0</version>
           <exclusions>
               <exclusion>
                   <groupId>C</groupId>
                   <artifactId>C</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
      
    5. 依赖管理

      这在之前 优化 已经提到, 采取在父级项目中定义 dependencyManagement, pluginManagement, 在子级中沿用父级的版本, 仅需要列出所选取的 依赖坐标, 而无需再度定义版本(如果定义子级版本, 父级就会被忽略);

      多模块项目:

       <modules>
           <module>project-a</module>
           <module>project-b</module>
       </modules>
      

      多模块项目的打包总是一个 POM 而非构建, 其中各个模块可以为 POM 或者 jar

      项目继承:

       <parent>
           <groupId>C</groupId>
           <artifactId>C</artifactId>
           <version>1.0-SNAPSHOT</version>
       </parent>
      

      可以被继承的项目:

      • 定义符: groupId 和 artifactId 必须有一个被重写, 不能有完全相同的坐标.
      • 依赖
      • 开发者和贡献者
      • 插件列表
      • 报告列表
      • 插件执行
      • 插件配置

      继承中, 当 父级 POM 在 父目录../pom.xml 或者 在 本地仓库目录时 可用, 否则的话需要指明 父级POM的相对位置.

        <parent>
           <groupId>C</groupId>
           <artifactId>C</artifactId>
           <version>1.0-SNAPSHOT</version>
           <relativePath>../a-parent/pom.xml</relativePath>
       </parent>
      

    暂时告一段落.

  • 相关阅读:
    Windows Phone 8 Wallet 手机钱包 / 电子钱包
    Windows Phone 8 In app purchase 应用内购买 / 应用内支付
    Windows Phone 8 适应多屏分辨率
    Windows phone 8 基于定位的后台应用
    Windows Phone 8 Nokia地图控件
    Windows Phone 8 MDIL编译与代码混淆工具
    Windows Phone 8 近场通信 NFC / Bluetooth Proximity
    Windows Phone 8 镜头应用 Lenses for Windows Phone 8
    Windows Phone 8 与 windows 8 开发技术概览
    嵌入式成长轨迹54 【Zigbee项目】【CC2430基础实验】【系统睡眠工作状态】
  • 原文地址:https://www.cnblogs.com/zyzdisciple/p/7999802.html
Copyright © 2011-2022 走看看