Maven 拾遗

01. maven 概要

   首先我把 maven 的概念快速的梳理一下,让我们快速地建立起一个比较精确的 maven 应用场景。

   maven 不是 ant,也不是 make,以前接触的构建工具,需要写一些详细的步骤,如: compile project1/src/*.java 等类似的语句。

   maven 采用了"约定优于配置"的方法,一些开发常用的操作和步骤已经固化在 maven中,所以使用者不再需要编写那些语句。

   maven 内置了开发流程的支持,它不仅能够编译,同样能够打包、发布,也能够一气呵成做完这些所有的步骤。

   maven 不是 ivy,依赖管理是 maven 的功能之一,maven 在依赖关系中加入了scope 的概念,进一步细化了依赖关系的划分。

   maven 将自己定位为一个项目管理工具。它负责管理项目开发过程中的如下几乎所有的东西。

   a.版本:maven有自己的版本定义和规则;

   b.构建:maven支持许多种的应用程序类型,对于每一种支持的应用程序类型都定义好了一组构建规则和工具集;

   c.输出物管理:maven可以管理项目构建的产物,并将其加入到用户库中。这个功能可以用于项目组和其他部门之间的交付行为; 

   d.依赖关系 : maven对依赖关系的特性进行细致的分析和划分,避免开发过程中的依赖混乱和相互污染行为;

   e.文档和构建结果:maven的site命令支持各种文档信息的发布,包括构建过程的各种输出,javadoc,产品文档等;

   f.项目关系:一个大型的项目通常有几个小项目或者模块组成,用maven可以很方便地管理;

   h.移植性管理 : maven可以针对不同的开发场景,输出不同种类的输出结果;

02. maven 生命周期

   

   maven把项目的构建划分为不同的生命周期(lifecycle),包括:验证、编译、测试、打包、部署。

   maven中所有的执行动作(goal)都需要指明自己在这个过程中的执行位置,然后maven执行的时候,就依照过程的发展依次调用这些goal进行各种处理。

   这个也是maven的一个基本调度机制。一般来说,位置稍后的过程都会依赖于之前的过程。

   当然,maven同样提供配置文件,可以依照用户要求,跳过某些阶段。

03. maven "约定优于配置"

   

   maven 中 "约定优于配置" 并不是完全不可以修改的,他们只是一些配置的默认值而已。

   但是使用者除非必要,并不需要去修改那些约定内容。

   maven默认的文件存放结构如下:

   /项目目录 pom.xml 用于maven的配置文件

   /src 源代码目录

   /src/main 工程源代码目录

   /src/main/java 工程java源代码目录

   /src/main/resource 工程的资源目录

   /src/test 单元测试目录

   /src/test/java

   /target 输出目录,所有的输出物都存放在这个目录下

   /target/classes 编译之后的class文件

   每一个阶段的任务都知道怎么正确完成自己的工作。

   如 compile 任务就知道从 src/main/java 下编译所有的 java 文件,并把它的输出class文件存放到 target/classes 中。

   采用"约定优于配置"的策略可以减少修改配置的工作量,也可以降低学习成本,更重要的是,给项目引入了统一的规范。

04. maven 版本规范

              <groupId>org.springframework</groupId>
              <artifactId>spring-webmvc</artifactId>
              <version>4.3.7.RELEASE</version>

   maven 使用4个要素来唯一定位某一个输出物: groupId:artifactId:packaging:version 。如 org.springframework:spring:2.5 。

   groupId 团体,公司,小组,组织,项目,或者其它团体。团体标识的约定是,它以创建这个项目的组织名称的逆向域名开头。

   artifactId 在groupId下的表示一个单独项目的唯一标识符。比如我们的 tomcat, commons 等。不要在 artifactId 中包含点号(.)。 

   version 一个项目的特定版本。发布项目有一个固定的版本标识来指向该项目的某一个特定的版本。

   虽然项目的打包格式也是 Maven 坐标的重要组成部分,但是它不是项目唯一标识符的一个部分。

   一个项目的 groupId:artifactId:version 使之成为一个独一无二的项目;你不能同时有一个拥有同样的 groupId, artifactId,version 标识的项目。

   packaging 项目的类型,默认是 jar,描述了项目打包后的输出。

   maven 在版本管理时候可以使用几个特殊的字符串 SNAPSHOT ,LATEST ,RELEASE 。

   比如"1.0-SNAPSHOT"。各个部分的含义和处理逻辑如下说明:

   SNAPSHOT:用于开发过程,Maven 就会在安装或发布这个组件的时候将该符号展开为一个日期和时间值,转换为UTC时间。

   例如,"1.0-SNAPSHOT"会在2010年5月5日下午2点10分发布时候变成 1.0-20100505-141000-1。 

   LATEST:指某个特定构件的最新发布,这个发布可能是一个发布版,也可能是一个 snapsho t版,具体看哪个时间最后。 

   RELEASE:指最后一个发布版。

05. maven 依赖管理

   个人认为依赖管理是 maven 中最吸引人的功能特性,这个特性让开发者只需要关注代码的直接依赖。

   比如我们用了spring,就加入spring 依赖说明就可以了,至于 spring 自己还依赖哪些外部的东西,maven 帮我们搞定。

   任意一个外部依赖说明包含如下几个要素:groupId, artifactId, version, scope, type, optional。其中前3个是必须的,各自含义如下:

   这里的 version 可以用区间表达式来表示,比如 (2.0,) 表示>2.0,[2.0,3.0) 表示 2.0<=ver<3.0;多个条件之间用逗号分隔,比如[1,3),[5,7]。

   maven 认为程序对外部的依赖会随着程序的所处阶段和应用场景而变化,所以 maven 中的依赖关系有作用域(scope)的限制。

   scope 包含如下的取值:

   compile(编译范围)---> compile 是默认的范围,编译范围依赖在所有的classpath中可用,同时它们也会被打包。

   provided(已提供范围) ---> provided 依赖只有在当 JDK 或者一个容器已提供该依赖之后才使用。

   比如你开发了一个web应用,在编译 classpath 中需要可用的 Servlet API 来编译 servlet,又不想在打包好的 WAR 中包含这个 Servlet API。

   runtime(运行时范围 --> runtime 依赖在运行和测试系统的时候需要,但在编译的时候不需要。

   比如你可能在编译的时候只需要 JDBC API JAR,而只有在运行的时候才需要 JDBC 驱动实现。

   test(测试范围)--> test 范围依赖 在一般的 编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用。

   system(系统范围) --> system 范围依赖与 provided 类似,但是你必须显式的提供一个对于本地系统中 JAR 文件的路径。

    <dependency>
         <groupId>org.wltea</groupId>
         <artifactId>analyzer</artifactId>
         <version>2012_u6</version>
         <scope>system</scope>
         <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/analyzer-2012_u6.jar</systemPath>
     </dependency>

   注意该范围是不推荐使用的(你应该一直尽量去从公共或定制的Maven仓库中引用依赖)。

   type 一般在pom引用依赖时候出现,其他时候不用, optional 是否可选依赖。

   依赖也可以是可选的,比如我们代码中没有任何cache依赖,但是hibernate可能要配置cache,所以该cache的依赖就是可选的。

06. maven 多项目管理

   maven的多项目管理也是非常强大的。一般来说,maven要求同一个工程的所有子项目都放置到同一个目录下,每一个子目录代表一个项目,比如

   总项目/ pom.xml 总项目的 pom 配置文件

   子项目1/pom.xml 子项目1的 pom 文件

   子项目2/ pom.xml 子项目2的 pom 文件

   按照这种格式存放,就是继承方式,所有具体子项目的pom.xml都会继承总项目pom的内容,取值为子项目pom内容优先。

   要设置继承方式,首先要在总项目的pom中加入如下配置

<modules> 
  <module>simple-weather</module> 
  <module>simple-webapp</module> 
</modules> 

   其次在每个子项目中加入

<parent> 
  <groupId>org.sonatype.mavenbook.ch06</groupId> 
  <artifactId>simple-parent</artifactId> 
  <version>1.0</version> 
</parent>

   当然,继承不是唯一的配置文件共用方式,maven还支持引用方式。引用pom的方式更简单,在依赖中加入一个type为pom的依赖即可。

  <dependency> 
     <groupId>org.sonatype.mavenbook</groupId> 
     <artifactId>persistence-deps</artifactId> 
     <version>1.0</version> 
     <type>pom</type> 
  </dependency> 

07. maven 内置属性

  用户可以在maven中定义一些属性,然后在其他地方用${xxx}进行引用。比如:

  <properties> 
     <var1>value1</var1> 
  </properties> 

   maven 提供了三个隐式的变量,用来访问系统环境变量、POM信息和 maven 的 settings:

   env 暴露操作系统的环境变量,比如 env.PATH

   project 暴露 POM 中的内容,用点号(.)的路径来引用POM元素的值,比如 ${project.artifactId}。另外,java的系统属性比如user.dir等,也暴露在这里。 

   settings 暴露 maven 的 settings 的信息,也可以用点号(.)来引用。

08. maven profile

   profile 是 maven 的一个重要特性,它可以让 maven 能够自动适应外部的环境变化。

   比如同一个项目,在linux下编译linux的版本,在win下编译win的版本等。

   一个项目可以设置多个 profile,也可以在同一时间设置多个 profile 被激活(active)的。

   自动激活的 profile 的条件可以是各种各样的设定条件,组合放置在 activation 节点中,也可以通过命令行直接指定。

   profile 包含的其他配置内容可以覆盖掉 pom 定义的相应值。

   如果认为 profile 设置比较复杂,可以将所有的 profiles 内容移动到专门的 profiles.xml 文件中,不过记得和 pom.xml 放在一起。

09. maven 配置文件

   maven的主执行程序为 mvn.bat,linux下为mvn.sh,这两个程序都很简单,它们的共同用途就是收集一些参数,然后用 java.exe来运行maven的Main函数。

   maven 同样需要有配置文件,名字叫做 settings.xml,它放在两个地方,一个是 maven 安装目录的conf目录下,对所有使用该 maven 的用户都起作用。

   我们称为主配置文件,另外一个放在 %USERPROFILE%/.m2/settings.xml 下,我们成为用户配置文件,只对当前用户有效,且可以覆盖主配置文件的参数内容。

   还有就是项目级别的配置信息了,它存放在每一个 maven 管理的项目目录下,叫 pom.xml,主要用于配置项目相关的一些内容。

   当然,如果有必要用户也可以在 pom 中写一些配置,覆盖住配置文件和用户配置文件的设置参数内容。

   一般来说,settings文件配置的是比如repository库路径之类的全局信息,具体可以参考官方网站的文章。

10. maven 本地安装和中央库发布

   在maven中一般都会用到安装库文件的功能,一则是我们常用的hibernate要使用jmx库,但是因为sun的license限制,所以无法将其直接包含在repository中。

   所以我们使用mvn命令把jar安装到我们本地的repository中

 mvn install:install-file -DgroupId=com.sun.jdmk -DartifactId=jmxtools -Dversion=1.2.1 -Dpackaging=jar -Dfile=/path/to/file

   如果我们想把它安装到公司的repository中,需要使用命令

mvn deploy:deploy-file -DgroupId=com.sun.jdmk -DartifactId=jmxtools -Dversion=1.2.1 -Dpackaging=jar -Dfile=/path/to/file -Durl=公司私服地址

   对于我们的工程输出,如果需要放置到公司的repository中的话,可以通过配置 pom 来实现

<distributionManagement> 
   <repository> 
      <id>mycompany-repository</id> 
      <name>MyCompany Repository</name> 
      <url>公司私服地址</url> 
   </repository> 
</distributionManagement>

11. maven 常用命令

1. 创建Maven的普通java项目: 
   mvn archetype:create -DgroupId=packageName -DartifactId=projectName 
2. 创建Maven的Web项目: 
   mvn archetype:create -DgroupId=packageName -DartifactId=webappName -DarchetypeArtifactId=maven-archetype-webapp 
3. 编译源代码: mvn compile 
4. 编译测试代码:mvn test-compile 
5. 运行测试:mvn test 
6. 产生site:mvn site 
7. 打包:mvn package 
8. 在本地Repository中安装jar:mvn install 
9. 清除产生的项目:mvn clean 
10. 生成eclipse项目:mvn eclipse:eclipse 
11. 生成idea项目:mvn idea:idea 
12. 组合使用goal命令,如只打包不测试:mvn -Dtest package 
13. 编译测试的内容:mvn test-compile 
14. 只打jar包: mvn jar:jar 
15. 只测试而不编译,也不测试编译:mvn test -skipping compile -skipping test-compile 
( -skipping 的灵活运用,当然也可以用于其他组合命令) 
16. 清除eclipse的一些系统设置:mvn eclipse:clean
17. 修改项目版本 mvn versions:set -DnewVersion=1.2 然后 mvn versions:commit

 

posted @ 2017-06-08 11:31  Orson  阅读(876)  评论(0编辑  收藏  举报