转自:http://www.iteye.com/topic/973166

前言

Maven,发音是[`meivin],"专家"的意思。它是一个很好的项目管理工具,很早就进入了我的必备工具行列,但是这次为了把ABPM项目 完全迁移并应用maven,所以对maven进行了一些深入的学习。写这个学习笔记的目的,一个是为了自己备忘,二则希望能够为其他人学习使用maven 缩短一些时间。

maven概要

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

maven不是什么

读书时候要先限定范围,避免一些有害的遐想。要说maven不是什么,我们可以从如下几个要点来展开

  1. maven不是ant,也不是make。

    我们以前接触的构建工具,需要写一些详细的步骤,比如: compile project1/src/*.java

    等类似的语句。这些语句正是我们使用ant和make所要编写的东西。maven采用了"约定优于配置"的方法,一些开发常用的操作和步骤已经固化在
    maven中,所以使用者不再需要去编写那些烦人的语句了。同时,maven内置了开发流程的支持,它不仅能够编译,同样能够打包、发布,也能够一气呵成
    做完这些所有的步骤。

  2. maven不是ivy

    依赖管理是maven的功能之一,虽然很多人包括我以前都是只用它的依赖管理功能,但是要深入运用的话,我们就可以看到更多的内容。更重要的是,maven在依赖关系中加入了scope的概念,进一步细化了依赖关系的划分。

maven是什么

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

  1. 版本

    maven有自己的版本定义和规则

  2. 构建

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

  3. 输出物管理

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

  4. 依赖关系

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

  5. 文档和构建结果

    maven的site命令支持各种文档信息的发布,包括构建过程的各种输出,javadoc,产品文档等。

  6. 项目关系

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

  7. 移植性管理

    maven可以针对不同的开发场景,输出不同种类的输出结果。

maven的生命周期

maven把项目的构建划分为不同的生命周期(lifecycle),在我看来,划分的已经是非常仔细了,大家可以参考这里

。粗略一点的话,它这个过程(phase)包括:编译、测试、打包、集成测试、验证、部署。maven中所有的执行动作(goal)都需要指明自己在这个过程中的执行位置,然后maven执行的时候,就依照过程的发展依次调用这些goal进行各种处理。

这个也是maven的一个基本调度机制。一般来说,位置稍后的过程都会依赖于之前的过程。当然,maven同样提供了配置文件,可以依照用户要求,跳过某些阶段。

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中。

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

maven的版本规范

maven使用如下几个要素来唯一定位某一个输出物: groupId:artifactId:packaging:version

。比如 org.springframework:spring:2.5

。每个部分的解释如下:

  • groupId

    团体,公司,小组,组织,项目,或者其它团体。团体标识的约定是,它以创建这个项目的组织名称的逆向域名(reverse domain
    name)开头。来自Sonatype的项目有一个以com.sonatype开头的groupId,而Apache
    Software的项目有以org.apache开头的groupId。

  • artifactId

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

  • version

    一个项目的特定版本。发布的项目有一个固定的版本标识来指向该项目的某一个特定的版本。而正在开发中的项目可以用一个特殊的标识,这种标识给版本加上一个"SNAPSHOT"的标记。

    虽然项目的打包格式也是Maven坐标的重要组成部分,但是它不是项目唯一标识符的一个部分。一个项目的
    groupId:artifactId:version使之成为一个独一无二的项目;你不能同时有一个拥有同样的groupId,
    artifactId和version标识的项目。

  • packaging

    项目的类型,默认是jar,描述了项目打包后的输出。类型为jar的项目产生一个JAR文件,类型为war的项目产生一个web应用。

  • classifier

    很少使用的坐标,一般都可以忽略classifiers。如果你要发布同样的代码,但是由于技术原因需要生成两个单独的构件,你就要使用一个分类器
    (classifier)。例如,如果你想要构建两个单独的构件成JAR,一个使用Java 1.4编译器,另一个使用Java
    6编译器,你就可以使用分类器来生成两个单独的JAR构件,它们有同样的groupId:artifactId:version组合。如果你的项目使用本
    地扩展类库,你可以使用分类器为每一个目标平台生成一个构件。分类器常用于打包构件的源码,JavaDoc或者二进制集合。

maven有自己的版本规范,一般是如下定义 <major version>.<minor version>.<incremental version>-<qualifier>


比如1.2.3-beta-01。要说明的是,maven自己判断版本的算法是major,minor,incremental部分用数字比
较,qualifier部分用字符串比较,所以要小心 alpha-2和alpha-15的比较关系,最好用 alpha-02的格式。

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

,LATEST

,RELEASE

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

  • SNAPSHOT

    如果一个版本包含字符串"SNAPSHOT",Maven就会在安装或发布这个组件的时候将该符号展开为一个日期和时间值,转换为UTC时间。例
    如,"1.0-SNAPSHOT"会在2010年5月5日下午2点10分发布时候变成1.0-20100505-141000-1。

    这个词只能用于开发过程中,因为一般来说,项目组都会频繁发布一些版本,最后实际发布的时候,会在这些snapshot版本中寻找一个稳定的,用于正式发
    布,比如1.4版本发布之前,就会有一系列的1.4-SNAPSHOT,而实际发布的1.4,也是从中拿出来的一个稳定版。

  • LATEST

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

  • RELEASE

    指最后一个发布版。

maven的组成部分

maven把整个maven管理的项目分为几个部分,一个部分是源代码,包括源代码本身、相关的各种资源,一个部分则是单元测试用例,另外一部分则是各种maven的插件。对于这几个部分,maven可以独立管理他们,包括各种外部依赖关系。

maven的依赖管理

依赖管理一般是最吸引人使用maven的功能特性了,这个特性让开发者只需要关注代码的直接依赖,比如我们用了spring,就加入spring依赖说明就可以了,至于spring自己还依赖哪些外部的东西,maven帮我们搞定。

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

  • groupId 必须
  • artifactId 必须
  • version 必须。

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

  • scope 作用域限制
  • type 一般在pom引用依赖时候出现,其他时候不用
  • optional 是否可选依赖

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

  • compile(编译范围)

    compile是默认的范围;如果没有提供一个范围,那该依赖的范围就是编译范围。编译范围依赖在所有的classpath中可用,同时它们也会被打包。

  • provided(已提供范围)

    provided依赖只有在当JDK或者一个容器已提供该依赖之后才使用。例如,如果你开发了一个web应用,你可能在编译classpath中需要可用
    的Servlet API来编译一个servlet,但是你不会想要在打包好的WAR中包含这个Servlet API;这个Servlet API
    JAR由你的应用服务器或者servlet容器提供。已提供范围的依赖在编译classpath(不是运行时)可用。它们不是传递性的,也不会被打包。

  • runtime(运行时范围)

    runtime依赖在运行和测试系统的时候需要,但在编译的时候不需要。比如,你可能在编译的时候只需要JDBC API JAR,而只有在运行的时候才需要JDBC驱动实现。

  • test(测试范围)

    test范围依赖 在一般的 编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用。测试范围依赖在之前的???中介绍过。

  • system(系统范围)

    system范围依赖与provided类似,但是你必须显式的提供一个对于本地系统中JAR文件的路径。这么做是为了允许基于本地对象编译,而这些对象是系统类库的一部分。这样的构件应该是一直可用的,Maven也不会在仓库中去寻找它。 如果你将一个依赖范围设置成系统范围,你必须同时提供一个systemPath元素

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

另外,代码有代码自己的依赖,各个maven使用的插件也可以有自己的依赖关系。依赖也可以是可选的,比如我们代码中没有任何cache依赖,但是hibernate可能要配置cache,所以该cache的依赖就是可选的。

多项目管理

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

  • 总项目/

    • pom.xml 总项目的pom配置文件
    • 子项目1/
      • pom.xml 子项目1的pom文件
    • 子项目2/
      • pom.xml 子项目2的pom文件

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

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

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

即可。

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

    <project>
<description>This is a project requiring JDBC</description>
...
<dependencies>
...
<dependency>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>persistence-deps</artifactId>
<version>1.0</version>
<type>pom</type>
</dependency>
</dependencies>
</project>

 属性

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

    <project>
<modelVersion>4.0.0</modelVersion>
...
<properties>
<var1>value1</var1>
</properties>
</project>

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

  • env

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

  • project

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

  • settings

    暴露maven的settings的信息,也可以用点号(.)来引用。maven把系统配置文件存放在maven的安装目录中,把用户相关的配置文件存放
    在~/.m2/settings.xml(unix)或者%USERPROFILE%/.m2/settings.xml(windows)中。

maven的profile

profile是maven的一个重要特性,它可以让maven能够自动适应外部的环境变化,比如同一个项目,在linux下编译linux的版
本,在win下编译win的版本等。一个项目可以设置多个profile,也可以在同一时间设置多个profile被激活(active)的。自动激活的
profile的条件可以是各种各样的设定条件,组合放置在activation节点中,也可以通过命令行直接指定。profile包含的其他配置内容可
以覆盖掉pom定义的相应值。如果认为profile设置比较复杂,可以将所有的profiles内容移动到专门的 profiles.xml

文件中,不过记得和pom.xml放在一起。

activation节点中的激活条件中常见的有如下几个:

  1. os

    判断操作系统相关的参数,它包含如下可以自由组合的子节点元素

    • message - 规则失败之后显示的消息
    • arch - 匹配cpu结构,常见为x86
    • family - 匹配操作系统家族,常见的取值为:dos,mac,netware,os/2,unix,windows,win9x,os/400等
    • name - 匹配操作系统的名字
    • version - 匹配的操作系统版本号
    • display - 检测到操作系统之后显示的信息
  2. jdk

    检查jdk版本,可以用区间表示。

  3. property

    检查属性值,本节点可以包含name和value两个子节点。

  4. file

    检查文件相关内容,包含两个子节点:exists和missing,用于分别检查文件存在和不存在两种情况。

maven的操作和使用

maven的操作有两种方式,一种是通过mvn命令行命令,一种是使用maven的eclipse插件。因为使用eclipse的maven插件操作起来比较容易,这里就只介绍使用mvn命令行的操作。

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库路径之类的全局信息,具体可以参考官方网站的文章

创建新工程

要创建一个新的maven工程,我们需要给我们的工程指定几个必要的要素,就是maven产品坐标的几个要素:groupId, artifactId,如果愿意,你也可以指定version和package名称。我们先看一个简单的创建命令:

d:\work\temp>mvn archetype:create -DgroupId=com.abc -DartifactId=product1 -DarchetypeArtifactId=maven-archetype-webapp

首先看这里的命令行参数的传递结构,怪异的 -D参数=值 的方式是 java.exe

要求的方式。这个命令创建一个web工程,目录结构是一个标准的maven结构,如下:

D:.
└─mywebapp
│ pom.xml

└─src
└─main
├─resources
└─webapp
│ index.jsp

└─WEB-INF
web.xml

大家要注意,这里目录结构的布局实际上是由参数 archetypeArtifactId 来决定的,因为这里传入的是 maven-archetype-webapp 如果我们传入其他的就会创建不同的结构,默认值为 maven-archetype-quickstart ,有兴趣的读者可以参考更详细的列表 ,我把部分常用的列表在这里:

Artifact Group Version Repository Description

maven-archetype-j2ee-simple org.apache.maven.archetypes     A simple J2EE Java application
maven-archetype-marmalade-mojo org.apache.maven.archetypes     A Maven plugin development project using marmalade
maven-archetype-plugin org.apache.maven.archetypes     A Maven Java plugin development project
maven-archetype-portlet org.apache.maven.archetypes     A simple portlet application
maven-archetype-profiles org.apache.maven.archetypes      
maven-archetype-quickstart org.apache.maven.archetypes      
maven-archetype-simple org.apache.maven.archetypes      
maven-archetype-site-simple org.apache.maven.archetypes     A simple site generation project
maven-archetype-site org.apache.maven.archetypes     A more complex site project
maven-archetype-webapp org.apache.maven.archetypes     A simple Java web application
maven-archetype-har net.sf.maven-har 0.9   Hibernate Archive
maven-archetype-sar net.sf.maven-sar 0.9   JBoss Service Archive

大家可以参考更详细的 archetype:create 帮助archtype参考信息

maven的多项目管理

多项目管理是maven的主要特色之一,对于一个大型工程,用maven来管理他们之间复杂的依赖关系,是再好不过了。maven的项目配置之间的关系有两种:继承关系和引用关系。

maven默认根据目录结构来设定pom的继承关系,即下级目录的pom默认继承上级目录的pom。要设定两者之间的关系很简单,上级pom如下设置:

要记住的是,这里的module是目录名,不是子工程的artifactId。子工程如下设置:

引用关系是另外一种复用的方式,maven中配置引用关系也很简单,加入一个 typepom 的依赖即可。

但是无论是父项目还是引用项目,这些工程都必须用 mvn install 或者 mvn deploy 安装到本地库才行,否则会报告依赖没有找到,eclipse编译时候也会出错。

需要特别提出的是复用过程中,父项目的pom中可以定义 dependencyManagement 节点,其中存放依赖关系,但是这个依赖关系只是定义,不会真的产生效果,如果子项目想要使用这个依赖关系,可以在本身的 dependency 中添加一个简化的引用

这种方法可以避免版本号满天飞的情况。

安装库文件到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=http://aaa.ss.com/ss.xxx -DrepositoryId=release-repo

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

这里使用的scp方式提交库文件,还有其他方式可以使用,请参考faq部分。然后记得在你的settings.xml中加入这一内容

maven的变量

maven定义了很多变量属性,参考这里 http://docs.codehaus.org/display/MAVENUSER/MavenPropertiesGuide

  1. 内置属性

    • ${basedir } represents the directory containing pom.xml
    • ${version } equivalent to ${project.version } or ${pom.version }
  2. Pom/Project properties

    所有pom中的元素都可以用 project.

    前缀进行引用,以下是部分常用的

    • ${project.build.directory

      } results in the path to your "target" dir, this is the same as ${pom.project.build.directory

      }

    • ${project.build.

      outputD

      irectory

      }

      results in the path to your "target/classes" dir

    • ${project.name

      } refers to the name of the project.

    • ${project.version

      } refers to the version of the project.

    • ${project.build.finalName

      } refers to the final name of the file created when the built project is packaged

  3. 本地用户设定

    所有用的的 settings.xml 中的设定都可以通过 settings.

    前缀进行引用

    • ${settings.localRepository

      } refers to the path of the user's local repository.

    • ${maven.repo.local

      } also works for backward compatibility with maven1 ??

  4. 环境变量

    系统的环境变量通过 env.

    前缀引用

    • ${env.M2_HOME

      } returns the Maven2 installation path.

    • ${java.home

      } specifies the path to the current JRE_HOME environment use with relative paths to get for example:
      <jvm>${java.home}../bin/java.exe</jvm>

  5. java系统属性

    所有JVM中定义的java系统属性.

  6. 用户在pom中定义的自定义属性
    <project>
    ...
    <properties>
    <my.filter.value>hello</my.filter.value>
    </properties>
    ...
    </project>
    • ${my.filter.value } will result in hello if you inserted the above XML fragment in your pom.xml
  7. 上级工程的变量

    上级工程的pom中的变量用前缀 ${project.parent

    } 引用. 上级工程的版本也可以这样引用: ${parent.version

    }.

maven的使用

我们已经知道maven预定义了许多的阶段(phase),每个插件都依附于这些阶段,并且在进入某个阶段的时候,调用运行这些相关插件的功能。我们先来看完整的maven生命周期:

生命周期

阶段描述

validate 验证项目是否正确,以及所有为了完整构建必要的信息是否可用
generate-sources 生成所有需要包含在编译过程中的源代码
process-sources 处理源代码,比如过滤一些值
generate-resources 生成所有需要包含在打包过程中的资源文件
process-resources 复制并处理资源文件至目标目录,准备打包
compile 编译项目的源代码
process-classes 后处理编译生成的文件,例如对Java类进行字节码增强(bytecode enhancement)
generate-test-sources 生成所有包含在测试编译过程中的测试源码
process-test-sources 处理测试源码,比如过滤一些值
generate-test-resources 生成测试需要的资源文件
process-test-resources 复制并处理测试资源文件至测试目标目录
test-compile 编译测试源码至测试目标目录
test 使用合适的单元测试框架运行测试。这些测试应该不需要代码被打包或发布
prepare-package 在真正的打包之前,执行一些准备打包必要的操作。这通常会产生一个包的展开的处理过的版本(将会在Maven 2.1+中实现)
package 将编译好的代码打包成可分发的格式,如JAR,WAR,或者EAR
pre-integration-test 执行一些在集成测试运行之前需要的动作。如建立集成测试需要的环境
integration-test 如果有必要的话,处理包并发布至集成测试可以运行的环境
post-integration-test 执行一些在集成测试运行之后需要的动作。如清理集成测试环境。
verify 执行所有检查,验证包是有效的,符合质量规范
install 安装包至本地仓库,以备本地的其它项目作为依赖使用
deploy 复制最终的包至远程仓库,共享给其它开发人员和项目(通常和一次正式的发布相关)

maven核心的插件列表可以参考 http://maven.apache.org/plugins/index.html

。这里仅列举几个常用的插件及其配置参数:

  1. clean插件

    只包含一个goal叫做 clean:clean

    ,负责清理构建时候创建的文件。 默认清理的位置是如下几个变量指定的路径 project.build.directory, project.build.outputDirectory, project.build.testOutputDirectory, and project.reporting.outputDirectory

  2. compiler插件

    包含2个goal,分别是 compiler:compile

    compiler:testCompile

    。可以到这里查看两者的具体参数设置:compile

    , testCompile

  3. surefire插件

    运行单元测试用例的插件,并且能够生成报表。包含一个goal为 surefire:test

    。主要参数testSourceDirectory用来指定测试用例目录,参考完整用法帮助

  4. jar

    负责将工程输出打包到jar文件中。包含两个goal,分别是 jar:jar

    , jar:test-jar

    。两个goal负责从classesDirectory或testClassesDirectory中获取所有资源,然后输出jar文件到outputDirectory中。

  5. war

    负责打包成war文件。常用goal有 war:war

    ,负责从warSourceDirectory(默认${basedir}/src/main/webapp)打包所有资源到outputDirectory中。

  6. resources

    负责复制各种资源文件,常用goal有 resources:resources

    ,负责将资源文件复制到outputDirectory中,默认为${project.build.outputDirectory}。

  7. install

    负责将项目输出(install:install)或者某个指定的文件(install:install-file)加入到本机库%USERPROFILE%/.m2/repository中。可以用 install:help

    寻求帮助。

  8. deploy

    负责将项目输出(deploy:deploy)或者某个指定的文件(deploy:deploy-file)加入到公司库中。

  9. site

    将工程所有文档生成网站,生成的网站界面默认和apache的项目站点类似,但是其文档用doxia格式写的,目前不支持docbook,需要用其他插件配合才能支持。

maven的使用问答

除了以下的几个faq条目之外,还有一些faq可以参考

  1. maven 自己的FAQ

兄弟们如果有其他问题,欢迎跟帖提问!

依赖关系

问:如何增加删除一个依赖关系?

答:直接在pom文件中加入一个dependency节点,如果要删除依赖,把对应的dependency节点删除即可。

问:如何屏蔽一个依赖关系?比如项目中使用的libA依赖某个库的1.0版,libB以来某个库的2.0版,现在想统一使用2.0版,如何去掉1.0版的依赖?

答:设置exclusion即可。

  1. <dependency>
  2. <groupId>org.hibernate</groupId>
  3. <artifactId>hibernate</artifactId>
  4. <version>3.2.5.ga</version>
  5. <exclusions>
  6. <exclusion>
  7. <groupId>javax.transaction</groupId>
  8. <artifactId>jta</artifactId>
  9. </exclusion>
  10. </exclusions>
  11. </dependency>
 
问:我有一些jar文件要依赖,但是我又不想把这些jar去install到mvn的repository中去,怎么做配置?

答:加入一个特殊的依赖关系,使用system类型,如下:

<dependency>
<groupId>com.abc</groupId>
<artifactId>my-tools</artifactId>
<version>2.5.0</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${basedir}/lib/mylib1.jar</systemPath>
</dependency>
 

但是要记住,发布的时候不会复制这个jar。需要手工配置,而且其他project依赖这个project的时候,会报告警告。如果没有特殊要求,建议直接注册发布到repository。

问:在eclipse环境中同时使用maven builder和eclipse builder,并且设置项目依赖关系之后,为什么编译会出现artifact找不到错误,但是直接使用命令行mvn构建则一切正常?

答:在project属性中去掉java build path中对其他 project 的依赖关系,直接在pom中设置依赖关系即可

<!-- 依赖的其他项目 -->
<dependency>
<groupId>com.abc.project1</groupId>
<artifactId>abc-project1-common</artifactId>
<version>${project.version}</version>
</dependency>
 

另外,保证没有其他错误。

问:我想让输出的jar包自动包含所有的依赖

答:使用 assembly 插件即可。

<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
 
问:我的测试用例依赖于其他工程的测试用例,如何设置?

答:maven本身在发布的时候,可以发布单纯的jar,也可以同时发布xxx-tests.jar和xxx-javadoc.jar(大家经常在repository中可以看到类似的东西)。我们自己的项目A要同时输出test.jar可以做如下的设置

<!-- 用于把test代码也做成一个jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
 

然后在其他需要引用的工程B中做如下的dependency设置

  1. <dependency>
  2. <groupId>com.abc.XXX</groupId>
  3. <artifactId>工程A</artifactId>
  4. <version>${project.version}</version>
  5. <type>test-jar</type>
  6. <scope>test</scope>
  7. </dependency>
 

变量

问:如何使用变量替换?项目中的某个配置文件比如jdbc.properties使用了一些pom中的变量,如何在发布中使用包含真实内容的最终结果文件?

答:使用资源过滤功能,比如:

<project>
..
<properties>
<jdbc.driverClassName>com.mysql.jdbc.Driver</jdbc.driverClassName>
<jdbc.url>jdbc:mysql://localhost:3306/development_db</jdbc.url>
<jdbc.username>dev_user</jdbc.username>
<jdbc.password>s3cr3tw0rd</jdbc.password>
</properties>
..
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
..
<profiles>
<profile>
<id>production</id>
<properties>
<jdbc.driverClassName>oracle.jdbc.driver.OracleDriver</jdbc.driverClassName>
<jdbc.url>jdbc:oracle:thin:@proddb01:1521:PROD</jdbc.url>
<jdbc.username>prod_user</jdbc.username>
<jdbc.password>s00p3rs3cr3t</jdbc.password>
</properties>
</profile>
</profiles>
</project>
 
问: maven-svn-revision-number-plugin 插件说明

答: maven-svn-revision-number-plugin 可以从 SVN 中获取版本号,并将其变成环境变量,交由其他插件或者profile使用,详细帮助在这里 。一般和resource的filter机制同时使用

<plugins>
<plugin>
<groupId>com.google.code.maven-svn-revision-number-plugin</groupId>
<artifactId>maven-svn-revision-number-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<entries>
<entry>
<prefix>prefix</prefix>
</entry>
</entries>
</configuration>
</plugin>
</plugins>
 

这段代码负责把resource文件中的内容替换成适当内容

repository = ${prefix.repository}
path = ${prefix.path}
revision = ${prefix.revision}
mixedRevisions = ${prefix.mixedRevisions}
committedRevision = ${prefix.committedRevision}
status = ${prefix.status}
specialStatus = ${prefix.specialStatus}

编译

问:如何给插件指派参数?比如我要设置一些编译参数

答:以下内容设定编译器编译java1.5的代码

<project>
...
<build>
...
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
...
</build>
...
</project>
 

要设置其他插件的参数也可以,请参考对应插件的帮助信息

问:我的目录是非标准的目录结构,如何设置让maven支持?

答:指定source目录和test-source目录即可。

<build>
<directory>target</directory>
<sourceDirectory>src</sourceDirectory>
<scriptSourceDirectory>js/scripts</scriptSourceDirectory>
<testSourceDirectory>test</testSourceDirectory>
<outputDirectory>bin</outputDirectory>
<testOutputDirectory>bin</testOutputDirectory>
</build>
 

这个例子把源代码设置成了src目录,测试代码在test目录,所以输出到bin目录。这里要注意,directory如果也设置成bin目录的 话,maven打包的时候会引起死循环,因为directory是所有工作存放的地方,默认包含outputDirectory定义的目录在内。

【转】maven常见问题问答的更多相关文章

  1. maven常见问题问答

    1.前言 Maven,发音是[`meivin],"专家"的意思.它是一个很好的项目管理工具,很早就进入了我的必备工具行列,但是这次为了把project1项目完全迁移并应用maven ...

  2. maven常见问题问答(转)

    转自:http://www.oschina.net/question/158170_29368 1.前言 Maven,发音是[`meivin],"专家"的 意思.它是一个很好的项目 ...

  3. Maven 常见问题

    1.前言 Maven,发音是[`meivin],"专家"的意思.它是一个很好的项目管理工具,很早就进入了我的必备工具行列,但是这次为了把project1项目完全迁移并应用maven ...

  4. maven常见问题

    maven常见错误: 一..在Eclipse导入已存在工作空间的项目,出现 情况1: Scanning errors (1):1 Could not read pom.xml 就是pom.xml出现了 ...

  5. 有关使用Maven常见问题总结(Eclipse中使用Maven、Maven项目部署到tomcat等问题)

    http://blog.csdn.net/sunitjy/article/details/42709311 ********************************************** ...

  6. maven常见问题归纳

    前言 Maven,发音是[`meivin],"专家"的意思.它是一个非常好的项目管理工具,非常早就进入了我的必备工具行列,可是这次为了把ABPM项目 全然迁移并应用maven,所以 ...

  7. maven常见问题汇总

    package阶段得到的是build目录下编译后的类包(jar),install是把这个包和一些maven的元信息(比如pom.xml)复制到本地仓库,assembly一般是把build结果和一些资源 ...

  8. maven常见问题处理(3-2)maven打包时跳过测试的几个方法

    运行mvn install时跳过Test方法一:<project> [...] <build> <plugins> <plugin> <group ...

  9. maven常见问题处理(3-3)Gradle编译时下载依赖失败解决方法

    Gradle编译时在本地仓库中如果没有发现依赖,就会从远程仓库中下载, 默认的远程仓库为 mavenCentral(),即 http://repo1.maven.org/maven2/往往访问速度特别 ...

随机推荐

  1. CodeForces 779E Bitwise Formula

    位运算,枚举. 按按分开计算,枚举$?$是$0$还是$1$,分别计算出$sum$,然后就可以知道该位需要填$1$还是$0$了. #include<map> #include<set& ...

  2. 解决Linux环境下安装xampp之后外部无法连接MySQL的问题

    在Linux系统下,开发PHP一般都是LAMP环境,对于开发环境来讲,没有必要花太大精力去单独配置LAMP环境,采用xampp一键安装包是一个很好的方式.在Linux系统上安装xampp的过程这里就不 ...

  3. 函数的扩展--ES6

    箭头函数 由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号. var f = () => ({a:1}); f(); // 返回 {a: 1} 若写成: var ...

  4. [BZOJ 1562] 变换序列

    Link: BZOJ 1562 传送门 Solution: 一道比较考对$Hungry$算法理解的题目 首先可以轻松看出原序列和答案序列的对应关系,从而建出二分图匹配模型 下面的关键在于如何保证字典序 ...

  5. 设计BBS

    功能分析: 1 登陆功能(基于ajax,图片验证码) 2 注册功能(基于ajax,基于forms验证) 3 博客首页 4 个人站点 5 文章详情 6 点赞,点踩 7 评论 --根评论 --子评论 8 ...

  6. [AGC025D]Choosing Points

    [AGC025D]Choosing Points 题目大意: 输⼊\(n(n\le300),d_1,d_2\),你要找到\(n^2\)个整点\((x,y)\)满⾜\(0\le x,y<2n\). ...

  7. Jedis笔记

    Sting: Jedis jedis=RedisClient.getResource(); jedis.set("hello", "world"); Syste ...

  8. ACM/CF赛制getstart模板

    (包含整型变量快速读入.简易循环和连续容器的迭代器循环的宏定义.调试时的运行时间输出(编译选项应有“DEBUG”宏定义)等)  1 /*================================ ...

  9. React-Router入门

    之前自己有在用React来重构之前写过的自己工作室官网,其中有用到React中的核心思想:组件,props,state.还有用Rap的接口来实现前后端交互请求(就是请求团队成员的信息部分).自己觉得还 ...

  10. TabControl控件和TabPage

    TabControl控件和TabPageTabControl控件可以支持在一个控件里面放置多个选项卡,每个选项卡又可以放置多个控件 由于在控件属性窗口添加选项卡相对比较容易,下面说一下动态创建选项卡 ...