maven整理

来源:互联网 发布:美化手机桌面主题软件 编辑:程序博客网 时间:2024/05/29 13:33

一、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/maven-v4_0_0.xsd">      <!--父项目的坐标。如果项目中没有规定某个元素的值,那么父项目中的对应值即为项目的默认值。 坐标包括group ID,artifact ID和 version。-->    <parent>     <!--被继承的父项目的构件标识符-->     <artifactId/>     <!--被继承的父项目的全球唯一标识符-->     <groupId/>     <!--被继承的父项目的版本-->     <version/>     <!--父项目的pom.xml文件的相对路径。相对路径允许你选择一个不同的路径。默认值是../pom.xml。Maven首先在构建当前项目的地方寻找父项目的pom,其次在文件系统的这个位置(relativePath位置),然后在本地仓库,最后在远程仓库寻找父项目的pom。-->     <relativePath/> </parent> <!--声明项目描述符遵循哪一个POM模型版本。模型本身的版本很少改变,虽然如此,但它仍然是必不可少的,这是为了当Maven引入了新的特性或者其他模型变更的时候,确保稳定性。-->        <modelVersion>4.0.0</modelVersion>      <!--项目的全球唯一标识符,通常使用全限定的包名区分该项目和其他项目。并且构建时生成的路径也是由此生成, 如com.mycompany.app生成的相对路径为:/com/mycompany/app-->      <groupId>asia.banseon</groupId>      <!--构件的标识符,它和group ID一起唯一标识一个构件。换句话说,你不能有两个不同的项目拥有同样的artifact ID和groupID;在某个特定的group ID下,artifact ID也必须是唯一的。构件是项目产生的或使用的一个东西,Maven为项目产生的构件包括:JARs,源码,二进制发布和WARs等。-->      <artifactId>banseon-maven2</artifactId>      <!--项目产生的构件类型,例如jar、war、ear、pom。插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型-->      <packaging>jar</packaging>      <!--项目当前版本,格式为:主版本.次版本.增量版本-限定版本号-->      <version>1.0-SNAPSHOT</version>      <!--项目的名称, Maven产生的文档用-->      <name>banseon-maven</name>      <!--项目主页的URL, Maven产生的文档用-->      <url>http://www.baidu.com/banseon</url>      <!--项目的详细描述, Maven 产生的文档用。  当这个元素能够用HTML格式描述时(例如,CDATA中的文本会被解析器忽略,就可以包含HTML标签), 不鼓励使用纯文本描述。如果你需要修改产生的web站点的索引页面,你应该修改你自己的索引页文件,而不是调整这里的文档。-->      <description>A maven project to study maven.</description>      <!--描述了这个项目构建环境中的前提条件。--> <prerequisites>  <!--构建该项目或使用该插件所需要的Maven的最低版本-->    <maven/> </prerequisites> <!--项目的问题管理系统(Bugzilla, Jira, Scarab,或任何你喜欢的问题管理系统)的名称和URL,本例为 jira-->      <issueManagement>     <!--问题管理系统(例如jira)的名字,-->          <system>jira</system>          <!--该项目使用的问题管理系统的URL-->        <url>http://jira.baidu.com/banseon</url>      </issueManagement>      <!--项目持续集成信息--> <ciManagement>  <!--持续集成系统的名字,例如continuum-->  <system/>  <!--该项目使用的持续集成系统的URL(如果持续集成系统有web接口的话)。-->  <url/>  <!--构建完成时,需要通知的开发者/用户的配置项。包括被通知者信息和通知条件(错误,失败,成功,警告)-->  <notifiers>   <!--配置一种方式,当构建中断时,以该方式通知用户/开发者-->   <notifier>    <!--传送通知的途径-->    <type/>    <!--发生错误时是否通知-->    <sendOnError/>    <!--构建失败时是否通知-->    <sendOnFailure/>    <!--构建成功时是否通知-->    <sendOnSuccess/>    <!--发生警告时是否通知-->    <sendOnWarning/>    <!--不赞成使用。通知发送到哪里-->    <address/>    <!--扩展配置项-->    <configuration/>   </notifier>  </notifiers> </ciManagement> <!--项目创建年份,4位数字。当产生版权信息时需要使用这个值。-->    <inceptionYear/>    <!--项目相关邮件列表信息-->      <mailingLists>     <!--该元素描述了项目相关的所有邮件列表。自动产生的网站引用这些信息。-->          <mailingList>           <!--邮件的名称-->            <name>Demo</name>              <!--发送邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建-->              <post>banseon@126.com</post>              <!--订阅邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建-->              <subscribe>banseon@126.com</subscribe>              <!--取消订阅邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建-->              <unsubscribe>banseon@126.com</unsubscribe>              <!--你可以浏览邮件信息的URL-->            <archive>http:/hi.baidu.com/banseon/demo/dev/</archive>          </mailingList>      </mailingLists>      <!--项目开发者列表-->      <developers>       <!--某个项目开发者的信息-->        <developer>           <!--SCM里项目开发者的唯一标识符-->            <id>HELLO WORLD</id>              <!--项目开发者的全名-->            <name>banseon</name>              <!--项目开发者的email-->            <email>banseon@126.com</email>              <!--项目开发者的主页的URL-->            <url/>            <!--项目开发者在项目中扮演的角色,角色元素描述了各种角色-->            <roles>                  <role>Project Manager</role>                  <role>Architect</role>              </roles>             <!--项目开发者所属组织-->             <organization>demo</organization>              <!--项目开发者所属组织的URL-->            <organizationUrl>http://hi.baidu.com/banseon</organizationUrl>              <!--项目开发者属性,如即时消息如何处理等-->            <properties>                  <dept>No</dept>              </properties>             <!--项目开发者所在时区, -11到12范围内的整数。-->             <timezone>-5</timezone>          </developer>      </developers>      <!--项目的其他贡献者列表-->      <contributors>     <!--项目的其他贡献者。参见developers/developer元素-->     <contributor>   <name/><email/><url/><organization/><organizationUrl/><roles/><timezone/><properties/>     </contributor>         </contributors>        <!--该元素描述了项目所有License列表。 应该只列出该项目的license列表,不要列出依赖项目的 license列表。如果列出多个license,用户可以选择它们中的一个而不是接受所有license。-->      <licenses>     <!--描述了项目的license,用于生成项目的web站点的license页面,其他一些报表和validation也会用到该元素。-->          <license>          <!--license用于法律上的名称-->             <name>Apache 2</name>              <!--官方的license正文页面的URL-->            <url>http://www.baidu.com/banseon/LICENSE-2.0.txt</url>              <!--项目分发的主要方式:              repo,可以从Maven库下载              manual, 用户必须手动下载和安装依赖-->            <distribution>repo</distribution>              <!--关于license的补充信息-->            <comments>A business-friendly OSS license</comments>          </license>      </licenses>      <!--SCM(Source Control Management)标签允许你配置你的代码库,供Maven web站点和其它插件使用。-->      <scm>          <!--SCM的URL,该URL描述了版本库和如何连接到版本库。欲知详情,请看SCMs提供的URL格式和列表。该连接只读。-->          <connection>              scm:svn:http://svn.baidu.com/banseon/maven/banseon/banseon-maven2-trunk(dao-trunk)           </connection>          <!--给开发者使用的,类似connection元素。即该连接不仅仅只读-->        <developerConnection>              scm:svn:http://svn.baidu.com/banseon/maven/banseon/dao-trunk           </developerConnection>        <!--当前代码的标签,在开发阶段默认为HEAD-->        <tag/>                <!--指向项目的可浏览SCM库(例如ViewVC或者Fisheye)的URL。-->          <url>http://svn.baidu.com/banseon</url>      </scm>      <!--描述项目所属组织的各种属性。Maven产生的文档用-->      <organization>       <!--组织的全名-->        <name>demo</name>          <!--组织主页的URL-->        <url>http://www.baidu.com/banseon</url>      </organization>    <!--构建项目需要的信息-->    <build>     <!--该元素设置了项目源码目录,当构建项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。-->  <sourceDirectory/>  <!--该元素设置了项目脚本源码目录,该目录和源码目录不同:绝大多数情况下,该目录下的内容 会被拷贝到输出目录(因为脚本是被解释的,而不是被编译的)。-->  <scriptSourceDirectory/>  <!--该元素设置了项目单元测试使用的源码目录,当测试项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。-->  <testSourceDirectory/>  <!--被编译过的应用程序class文件存放的目录。-->  <outputDirectory/>  <!--被编译过的测试class文件存放的目录。-->  <testOutputDirectory/>  <!--使用来自该项目的一系列构建扩展-->  <extensions>   <!--描述使用到的构建扩展。-->   <extension>    <!--构建扩展的groupId-->    <groupId/>    <!--构建扩展的artifactId-->    <artifactId/>    <!--构建扩展的版本-->    <version/>   </extension>  </extensions>  <!--当项目没有规定目标(Maven2 叫做阶段)时的默认值-->  <defaultGoal/>  <!--这个元素描述了项目相关的所有资源路径列表,例如和项目相关的属性文件,这些资源被包含在最终的打包文件里。-->  <resources>   <!--这个元素描述了项目相关或测试相关的所有资源路径-->   <resource>    <!--描述了资源的目标路径。该路径相对target/classes目录(例如${project.build.outputDirectory})。举个例子,如果你想资源在特定的包里(org.apache.maven.messages),你就必须该元素设置为org/apache/maven/messages。然而,如果你只是想把资源放到源码目录结构里,就不需要该配置。-->    <targetPath/>    <!--是否使用参数值代替参数名。参数值取自properties元素或者文件里配置的属性,文件在filters元素里列出。-->    <filtering/>    <!--描述存放资源的目录,该路径相对POM路径-->    <directory/>    <!--包含的模式列表,例如**/*.xml.-->    <includes/>    <!--排除的模式列表,例如**/*.xml-->    <excludes/>   </resource>  </resources>  <!--这个元素描述了单元测试相关的所有资源路径,例如和单元测试相关的属性文件。-->  <testResources>   <!--这个元素描述了测试相关的所有资源路径,参见build/resources/resource元素的说明-->   <testResource>    <targetPath/><filtering/><directory/><includes/><excludes/>   </testResource>  </testResources>  <!--构建产生的所有文件存放的目录-->  <directory/>  <!--产生的构件的文件名,默认值是${artifactId}-${version}。-->  <finalName/>  <!--当filtering开关打开时,使用到的过滤器属性文件列表-->  <filters/>  <!--子项目可以引用的默认插件信息。该插件配置项直到被引用时才会被解析或绑定到生命周期。给定插件的任何本地配置都会覆盖这里的配置-->  <pluginManagement>   <!--使用的插件列表 。-->   <plugins>    <!--plugin元素包含描述插件所需要的信息。-->    <plugin>     <!--插件在仓库里的group ID-->     <groupId/>     <!--插件在仓库里的artifact ID-->     <artifactId/>     <!--被使用的插件的版本(或版本范围)-->     <version/>     <!--是否从该插件下载Maven扩展(例如打包和类型处理器),由于性能原因,只有在真需要下载时,该元素才被设置成enabled。-->     <extensions/>     <!--在构建生命周期中执行一组目标的配置。每个目标可能有不同的配置。-->     <executions>      <!--execution元素包含了插件执行需要的信息-->      <execution>       <!--执行目标的标识符,用于标识构建过程中的目标,或者匹配继承过程中需要合并的执行目标-->       <id/>       <!--绑定了目标的构建生命周期阶段,如果省略,目标会被绑定到源数据里配置的默认阶段-->       <phase/>       <!--配置的执行目标-->       <goals/>       <!--配置是否被传播到子POM-->       <inherited/>       <!--作为DOM对象的配置-->       <configuration/>      </execution>     </executions>     <!--项目引入插件所需要的额外依赖-->     <dependencies>      <!--参见dependencies/dependency元素-->      <dependency>       ......      </dependency>     </dependencies>          <!--任何配置是否被传播到子项目-->     <inherited/>     <!--作为DOM对象的配置-->     <configuration/>    </plugin>   </plugins>  </pluginManagement>  <!--使用的插件列表-->  <plugins>   <!--参见build/pluginManagement/plugins/plugin元素-->   <plugin>    <groupId/><artifactId/><version/><extensions/>    <executions>     <execution>      <id/><phase/><goals/><inherited/><configuration/>     </execution>    </executions>    <dependencies>     <!--参见dependencies/dependency元素-->     <dependency>      ......     </dependency>    </dependencies>    <goals/><inherited/><configuration/>   </plugin>  </plugins> </build> <!--在列的项目构建profile,如果被激活,会修改构建处理--> <profiles>  <!--根据环境参数或命令行参数激活某个构建处理-->  <profile>   <!--构建配置的唯一标识符。即用于命令行激活,也用于在继承时合并具有相同标识符的profile。-->   <id/>   <!--自动触发profile的条件逻辑。Activation是profile的开启钥匙。profile的力量来自于它   能够在某些特定的环境中自动使用某些特定的值;这些环境通过activation元素指定。activation元素并不是激活profile的唯一方式。-->   <activation>    <!--profile默认是否激活的标志-->    <activeByDefault/>    <!--当匹配的jdk被检测到,profile被激活。例如,1.4激活JDK1.4,1.4.0_2,而!1.4激活所有版本不是以1.4开头的JDK。-->    <jdk/>    <!--当匹配的操作系统属性被检测到,profile被激活。os元素可以定义一些操作系统相关的属性。-->    <os>     <!--激活profile的操作系统的名字-->     <name>Windows XP</name>     <!--激活profile的操作系统所属家族(如 'windows')-->     <family>Windows</family>     <!--激活profile的操作系统体系结构 -->     <arch>x86</arch>     <!--激活profile的操作系统版本-->     <version>5.1.2600</version>    </os>    <!--如果Maven检测到某一个属性(其值可以在POM中通过${名称}引用),其拥有对应的名称和值,Profile就会被激活。如果值    字段是空的,那么存在属性名称字段就会激活profile,否则按区分大小写方式匹配属性值字段-->    <property>     <!--激活profile的属性的名称-->     <name>mavenVersion</name>     <!--激活profile的属性的值-->     <value>2.0.3</value>    </property>    <!--提供一个文件名,通过检测该文件的存在或不存在来激活profile。missing检查文件是否存在,如果不存在则激活    profile。另一方面,exists则会检查文件是否存在,如果存在则激活profile。-->    <file>     <!--如果指定的文件存在,则激活profile。-->     <exists>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/</exists>     <!--如果指定的文件不存在,则激活profile。-->     <missing>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/</missing>    </file>   </activation>   <!--构建项目所需要的信息。参见build元素-->   <build>    <defaultGoal/>    <resources>     <resource>      <targetPath/><filtering/><directory/><includes/><excludes/>     </resource>    </resources>    <testResources>     <testResource>      <targetPath/><filtering/><directory/><includes/><excludes/>     </testResource>    </testResources>    <directory/><finalName/><filters/>    <pluginManagement>     <plugins>      <!--参见build/pluginManagement/plugins/plugin元素-->      <plugin>       <groupId/><artifactId/><version/><extensions/>       <executions>        <execution>         <id/><phase/><goals/><inherited/><configuration/>        </execution>       </executions>       <dependencies>        <!--参见dependencies/dependency元素-->        <dependency>         ......        </dependency>       </dependencies>       <goals/><inherited/><configuration/>      </plugin>     </plugins>    </pluginManagement>    <plugins>     <!--参见build/pluginManagement/plugins/plugin元素-->     <plugin>      <groupId/><artifactId/><version/><extensions/>      <executions>       <execution>        <id/><phase/><goals/><inherited/><configuration/>       </execution>      </executions>      <dependencies>       <!--参见dependencies/dependency元素-->       <dependency>        ......       </dependency>      </dependencies>      <goals/><inherited/><configuration/>     </plugin>    </plugins>   </build>   <!--模块(有时称作子项目) 被构建成项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径-->   <modules/>   <!--发现依赖和扩展的远程仓库列表。-->   <repositories>    <!--参见repositories/repository元素-->    <repository>     <releases>      <enabled/><updatePolicy/><checksumPolicy/>     </releases>     <snapshots>      <enabled/><updatePolicy/><checksumPolicy/>     </snapshots>     <id/><name/><url/><layout/>    </repository>   </repositories>   <!--发现插件的远程仓库列表,这些插件用于构建和报表-->   <pluginRepositories>    <!--包含需要连接到远程插件仓库的信息.参见repositories/repository元素-->        <pluginRepository>     <releases>      <enabled/><updatePolicy/><checksumPolicy/>     </releases>     <snapshots>      <enabled/><updatePolicy/><checksumPolicy/>     </snapshots>     <id/><name/><url/><layout/>    </pluginRepository>   </pluginRepositories>   <!--该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。它们自动从项目定义的仓库中下载。要获取更多信息,请看项目依赖机制。-->   <dependencies>    <!--参见dependencies/dependency元素-->    <dependency>     ......    </dependency>   </dependencies>   <!--不赞成使用. 现在Maven忽略该元素.-->   <reports/>      <!--该元素包括使用报表插件产生报表的规范。当用户执行“mvn site”,这些报表就会运行。 在页面导航栏能看到所有报表的链接。参见reporting元素-->   <reporting>    ......   </reporting>   <!--参见dependencyManagement元素-->   <dependencyManagement>    <dependencies>     <!--参见dependencies/dependency元素-->     <dependency>      ......     </dependency>    </dependencies>   </dependencyManagement>   <!--参见distributionManagement元素-->   <distributionManagement>    ......   </distributionManagement>   <!--参见properties元素-->   <properties/>  </profile> </profiles> <!--模块(有时称作子项目) 被构建成项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径--> <modules/>    <!--发现依赖和扩展的远程仓库列表。-->      <repositories>       <!--包含需要连接到远程仓库的信息-->        <repository>          <!--如何处理远程仓库里发布版本的下载-->         <releases>          <!--true或者false表示该仓库是否为下载某种类型构件(发布版,快照版)开启。 -->    <enabled/>    <!--该元素指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳。这里的选项是:always(一直),daily(默认,每日),interval:X(这里X是以分钟为单位的时间间隔),或者never(从不)。-->    <updatePolicy/>    <!--当Maven验证构件校验文件失败时该怎么做:ignore(忽略),fail(失败),或者warn(警告)。-->    <checksumPolicy/>   </releases>   <!--如何处理远程仓库里快照版本的下载。有了releases和snapshots这两组配置,POM就可以在每个单独的仓库中,为每种类型的构件采取不同的策略。例如,可能有人会决定只为开发目的开启对快照版本下载的支持。参见repositories/repository/releases元素-->   <snapshots>    <enabled/><updatePolicy/><checksumPolicy/>   </snapshots>   <!--远程仓库唯一标识符。可以用来匹配在settings.xml文件里配置的远程仓库-->   <id>banseon-repository-proxy</id>     <!--远程仓库名称-->            <name>banseon-repository-proxy</name>              <!--远程仓库URL,按protocol://hostname/path形式-->            <url>http://192.168.1.169:9999/repository/</url>              <!--用于定位和排序构件的仓库布局类型-可以是default(默认)或者legacy(遗留)。Maven 2为其仓库提供了一个默认的布局;然而,Maven 1.x有一种不同的布局。我们可以使用该元素指定布局是default(默认)还是legacy(遗留)。-->            <layout>default</layout>                    </repository>      </repositories>    <!--发现插件的远程仓库列表,这些插件用于构建和报表-->    <pluginRepositories>     <!--包含需要连接到远程插件仓库的信息.参见repositories/repository元素-->  <pluginRepository>   ......  </pluginRepository> </pluginRepositories>        <!--该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。它们自动从项目定义的仓库中下载。要获取更多信息,请看项目依赖机制。-->      <dependencies>          <dependency>   <!--依赖的group ID-->            <groupId>org.apache.maven</groupId>              <!--依赖的artifact ID-->            <artifactId>maven-artifact</artifactId>              <!--依赖的版本号。 在Maven 2里, 也可以配置成版本号的范围。-->            <version>3.8.1</version>              <!--依赖类型,默认类型是jar。它通常表示依赖的文件的扩展名,但也有例外。一个类型可以被映射成另外一个扩展名或分类器。类型经常和使用的打包方式对应,尽管这也有例外。一些类型的例子:jar,war,ejb-client和test-jar。如果设置extensions为 true,就可以在plugin里定义新的类型。所以前面的类型的例子不完整。-->            <type>jar</type>            <!--依赖的分类器。分类器可以区分属于同一个POM,但不同构建方式的构件。分类器名被附加到文件名的版本号后面。例如,如果你想要构建两个单独的构件成JAR,一个使用Java 1.4编译器,另一个使用Java 6编译器,你就可以使用分类器来生成两个单独的JAR构件。-->            <classifier></classifier>            <!--依赖范围。在项目发布过程中,帮助决定哪些构件被包括进来。欲知详情请参考依赖机制。                 - compile :默认范围,用于编译                   - provided:类似于编译,但支持你期待jdk或者容器提供,类似于classpath                   - runtime: 在执行时需要使用                   - test:    用于test任务时使用                   - system: 需要外在提供相应的元素。通过systemPath来取得                   - systemPath: 仅用于范围为system。提供相应的路径                   - optional:   当项目自身被依赖时,标注依赖是否传递。用于连续依赖时使用-->              <scope>test</scope>                <!--仅供system范围使用。注意,不鼓励使用这个元素,并且在新的版本中该元素可能被覆盖掉。该元素为依赖规定了文件系统上的路径。需要绝对路径而不是相对路径。推荐使用属性匹配绝对路径,例如${java.home}。-->             <systemPath></systemPath>              <!--当计算传递依赖时, 从依赖构件列表里,列出被排除的依赖构件集。即告诉maven你只依赖指定的项目,不依赖项目的依赖。此元素主要用于解决版本冲突问题-->             <exclusions>             <exclusion>                      <artifactId>spring-core</artifactId>                      <groupId>org.springframework</groupId>                  </exclusion>              </exclusions>                <!--可选依赖,如果你在项目B中把C依赖声明为可选,你就需要在依赖于B的项目(例如项目A)中显式的引用对C的依赖。可选依赖阻断依赖的传递性。-->              <optional>true</optional>        </dependency>    </dependencies>     <!--不赞成使用. 现在Maven忽略该元素.-->    <reports></reports>    <!--该元素描述使用报表插件产生报表的规范。当用户执行“mvn site”,这些报表就会运行。 在页面导航栏能看到所有报表的链接。-->  <reporting>  <!--true,则,网站不包括默认的报表。这包括“项目信息”菜单中的报表。-->  <excludeDefaults/>  <!--所有产生的报表存放到哪里。默认值是${project.build.directory}/site。-->  <outputDirectory/>  <!--使用的报表插件和他们的配置。-->  <plugins>   <!--plugin元素包含描述报表插件需要的信息-->   <plugin>    <!--报表插件在仓库里的group ID-->    <groupId/>    <!--报表插件在仓库里的artifact ID-->    <artifactId/>    <!--被使用的报表插件的版本(或版本范围)-->    <version/>    <!--任何配置是否被传播到子项目-->    <inherited/>    <!--报表插件的配置-->    <configuration/>    <!--一组报表的多重规范,每个规范可能有不同的配置。一个规范(报表集)对应一个执行目标 。例如,有1,2,3,4,5,6,7,8,9个报表。1,2,5构成A报表集,对应一个执行目标。2,5,8构成B报表集,对应另一个执行目标-->    <reportSets>     <!--表示报表的一个集合,以及产生该集合的配置-->     <reportSet>      <!--报表集合的唯一标识符,POM继承时用到-->      <id/>      <!--产生报表集合时,被使用的报表的配置-->      <configuration/>      <!--配置是否被继承到子POMs-->      <inherited/>      <!--这个集合里使用到哪些报表-->      <reports/>     </reportSet>    </reportSets>   </plugin>  </plugins> </reporting> <!--继承自该项目的所有子项目的默认依赖信息。这部分的依赖信息不会被立即解析,而是当子项目声明一个依赖(必须描述group ID和artifact ID信息),如果group ID和artifact ID以外的一些信息没有描述,则通过group ID和artifact ID匹配到这里的依赖,并使用这里的依赖信息。-->  <dependencyManagement>  <dependencies>   <!--参见dependencies/dependency元素-->   <dependency>    ......   </dependency>  </dependencies> </dependencyManagement>        <!--项目分发信息,在执行mvn deploy后表示要发布的位置。有了这些信息就可以把网站部署到远程服务器或者把构件部署到远程仓库。-->      <distributionManagement>        <!--部署项目产生的构件到远程仓库需要的信息-->        <repository>         <!--是分配给快照一个唯一的版本号(由时间戳和构建流水号)?还是每次都使用相同的版本号?参见repositories/repository元素-->   <uniqueVersion/>   <id>banseon-maven2</id>     <name>banseon maven2</name>              <url>file://${basedir}/target/deploy</url>              <layout/>  </repository>  <!--构件的快照部署到哪里?如果没有配置该元素,默认部署到repository元素配置的仓库,参见distributionManagement/repository元素-->    <snapshotRepository>   <uniqueVersion/>   <id>banseon-maven2</id>             <name>Banseon-maven2 Snapshot Repository</name>             <url>scp://svn.baidu.com/banseon:/usr/local/maven-snapshot</url>     <layout/>  </snapshotRepository>  <!--部署项目的网站需要的信息-->          <site>         <!--部署位置的唯一标识符,用来匹配站点和settings.xml文件里的配置-->              <id>banseon-site</id>              <!--部署位置的名称-->            <name>business api website</name>              <!--部署位置的URL,按protocol://hostname/path形式-->            <url>                  scp://svn.baidu.com/banseon:/var/www/localhost/banseon-web               </url>          </site>  <!--项目下载页面的URL。如果没有该元素,用户应该参考主页。使用该元素的原因是:帮助定位那些不在仓库里的构件(由于license限制)。-->  <downloadUrl/>  <!--如果构件有了新的group ID和artifact ID(构件移到了新的位置),这里列出构件的重定位信息。-->  <relocation>   <!--构件新的group ID-->   <groupId/>   <!--构件新的artifact ID-->   <artifactId/>   <!--构件新的版本号-->   <version/>   <!--显示给用户的,关于移动的额外信息,例如原因。-->   <message/>  </relocation>  <!--给出该构件在远程仓库的状态。不得在本地项目中设置该元素,因为这是工具自动更新的。有效的值有:none(默认),converted(仓库管理员从Maven 1 POM转换过来),partner(直接从伙伴Maven 2仓库同步过来),deployed(从Maven 2实例部署),verified(被核实时正确的和最终的)。-->  <status/>            </distributionManagement>    <!--以值替代名称,Properties可以在整个POM中使用,也可以作为触发条件(见settings.xml配置文件里activation元素的说明)。格式是<name>value</name>。-->    <properties/></project>

2、maven安装

安装环境

  windowXP 32

下载地址

  http://maven.apache.org/download.cgi

安装包

  apache-maven-3.2.3.zip

 

 

一、安装

Step1 解压缩

下载完成得到的是一个压缩包文件,将它解压缩后就可以使用了。

Step2 配置环境变量

Step3 验证环境变量配置是否成功:mvn -v

 

二、 修改本地仓库路径

windows环境中,maven默认仓库位置:C:\Documents and Settings\Administrator\.m2\repository

1、建立存放仓库目录:d:\java\maven\repos

2、在解压缩目录下找到 conf 文件夹并打开,找到 settings.xml 配置文件并打开它:复制到步骤1的目录中。

3、修改两处的settings.xml设置,在里边添加一行配置<localRepository>d:\java\maven\repos</localRepository>,将本地仓库路径指定到你自己想要指定的目录当中。如下图:

 

三、 查看中央仓库路径

1、在解压缩目录下找到 lib文件夹打开,查看到maven-model-builder-3.3.1.jar
2、maven-model-builder-3.3.1.jar\org\apache\maven\model\pom-4.0.0.xml中有网络中央仓库地址。

 

四、 执行第一次任务:mvn help:system

执行这个指令需要几分钟的时间才能完成,在这期间,你所要做的事情就是等待,直到出现,BUILD SUCCESS。

打开本地仓库所在目录,发现里边多了好些个文件夹,这是Maven从远程中央仓库download回来的文件

可以想象,伴随着Maven的使用,以后这个目录下的文件夹会变的越来越多,所占用的磁盘空间也会变的越来越大,能达到好几个G的大小,
所以在配置本地仓库路径的时候,需要给它预留几个G大小的空间,这样就没什么问题了。

1、生成项目骨架 

命令:mvn archetype:generate -DgroupId=zttc.itat.maven -DartifactId=maven-ch01 -Dversion=0.0.1-SNAPSHOT

 

2、编译

命令:maven compile

3、测试

命令:maven test

4、清空

命令:mvn clean目标文件夹清空

5、打包

命令:mvn package,打包该程序为一个jar包或者war包。

6、安装

命令:mvn install   安装到本地仓库中

 

7、测试输出

命令:java -cp target/nameofjar.jar javamain

其中-cp命令是用于运行一个jar包并指定该jar包的main方法所在类。nameofjar.jar是指项目在target目录下打包项目生成的jar包,替换为自己的jar包名即可,另外javamain是指该jar的main方法所在类,包含该类的包名和类名。

事例:java -cp target/maven-ch01-0.0.1-SNAPSHOT.jar   zttc.itat.maven.HelloMaven


maven有三套生命周期

1.clean       清理项目

2.default     构建项目

3.site           建立项目站点

每套生命周期都包含了一些阶段,这些阶段是有序的,后面的阶段依赖前面的阶段,

以clean生命周期为例,它包括了pre-clean,clean和post-clean三个阶段,当我们调用pre-clean的时候, 只会执行pre-clean阶段;

当调用clean的时候,pre-clean和clean阶段会以顺序执行;当调用post-clean的时候,pre-clean,clean和post-clean三个阶段会以顺序执行。

 

这三套生命周期是相互独立的,可以仅仅调用clean声明周期的某个阶段, 或者调用default生命周期的某个阶段,而不会对其他生命周期产生任何影响。

clean生命周期共包含了三个阶段:
            pre-clean  执行一些需要在clean之前完成的工作
            clean  移除所有上一次构建生成的文件
            post-clean  执行一些需要在clean之后立刻完成的工作

default生命周期包含的阶段:
             validate
             initialize
             generate-sources
             process-sources
             generate-resources
             process-resources     复制并处理资源文件,至目标目录,准备打包。
             compile     编译项目的源代码。
             process-classes
             generate-test-sources  
             process-test-sources 
             generate-test-resources
             process-test-resources     复制并处理资源文件,至目标测试目录。
             test-compile     编译测试源代码。
             process-test-classes 
             test     使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署。
             prepare-package 
             package     接受编译好的代码,打包成可发布的格式,如 JAR 。
             pre-integration-test
             integration-test
             post-integration-test 
             verify 
             install     将包安装至本地仓库,以让其它项目依赖。
             deploy     将最终的包复制到远程的仓库,以让其它开发人员与项目共享。

site生命周期的各个阶段:
             pre-site     执行一些需要在生成站点文档之前完成的工作
             site    生成项目的站点文档
             post-site     执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
             site-deploy     将生成的站点文档部署到特定的服务器上
  

组合阶段执行

             mvn clean     调用的clean生命周期的clean阶段,实际执行的是pre-clean和clean阶段。

             mvn test         执行的是default生命周期的test阶段, 实际执行的是validate到test阶段。

             mvn clean  package      clean生命周期的pre-clean,clean阶段和 default生命周期的从validate到package阶段。



文件存放位置

全局配置: ${M2_HOME}/conf/settings.xml

用户配置: ${user.home}/.m2/settings.xml

note:用户配置优先于全局配置。${user.home} 和和所有其他系统属性只能在3.0+版本上使用。请注意windows和Linux使用变量的区别。

 

settings.xml详解

声明规范

<?xml version="1.0" encoding="UTF-8"?><settings 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/settings-1.0.0.xsd">

localRepository

 <!-- 本地仓库的路径。默认值为${user.home}/.m2/repository。 --> <localRepository>usr/local/maven</localRepository>

interactiveMode

 <!--Maven是否需要和用户交互以获得输入。如果Maven需要和用户交互以获得输入,则设置成true,反之则应为false。默认为true。--> <interactiveMode>true</interactiveMode>

usePluginRegistry

<!--Maven是否需要使用plugin-registry.xml文件来管理插件版本。如果需要让Maven使用文件${user.home}/.m2/plugin-registry.xml来管理插件版本,则设为true。默认为false。--> <usePluginRegistry>false</usePluginRegistry>

offline

 <!--表示Maven是否需要在离线模式下运行。如果构建系统需要在离线模式下运行,则为true,默认为false。当由于网络设置原因或者安全因素,构建服务器不能连接远程仓库的时候,该配置就十分有用。 --> <offline>false</offline>

pluginGroups

复制代码
<!--当插件的组织Id(groupId)没有显式提供时,供搜寻插件组织Id(groupId)的列表。该元素包含一个pluginGroup元素列表,每个子元素包含了一个组织Id(groupId)。当我们使用某个插件,并且没有在命令行为其提供组织Id(groupId)的时候,Maven就会使用该列表。默认情况下该列表包含了org.apache.maven.plugins和org.codehaus.mojo --> <pluginGroups>  <!--plugin的组织Id(groupId) -->  <pluginGroup>org.codehaus.mojo</pluginGroup> </pluginGroups>
复制代码

proxies

复制代码
<!--用来配置不同的代理,多代理profiles 可以应对笔记本或移动设备的工作环境:通过简单的设置profile id就可以很容易的更换整个代理配置。 --> <proxies>  <!--代理元素包含配置代理时需要的信息-->  <proxy>   <!--代理的唯一定义符,用来区分不同的代理元素。-->   <id>myproxy</id>   <!--该代理是否是激活的那个。true则激活代理。当我们声明了一组代理,而某个时候只需要激活一个代理的时候,该元素就可以派上用处。 -->   <active>true</active>   <!--代理的协议。 协议://主机名:端口,分隔成离散的元素以方便配置。-->   <protocol>http</protocol>   <!--代理的主机名。协议://主机名:端口,分隔成离散的元素以方便配置。  -->   <host>proxy.somewhere.com</host>   <!--代理的端口。协议://主机名:端口,分隔成离散的元素以方便配置。 -->   <port>8080</port>   <!--代理的用户名,用户名和密码表示代理服务器认证的登录名和密码。 -->   <username>proxyuser</username>   <!--代理的密码,用户名和密码表示代理服务器认证的登录名和密码。 -->   <password>somepassword</password>   <!--不该被代理的主机名列表。该列表的分隔符由代理服务器指定;例子中使用了竖线分隔符,使用逗号分隔也很常见。-->   <nonProxyHosts>*.google.com|ibiblio.org</nonProxyHosts>  </proxy> </proxies>
复制代码

servers

复制代码
<!--配置服务端的一些设置。一些设置如安全证书不应该和pom.xml一起分发。这种类型的信息应该存在于构建服务器上的settings.xml文件中。--> <servers>  <!--服务器元素包含配置服务器时需要的信息 -->  <server>   <!--这是server的id(注意不是用户登陆的id),该id与distributionManagement中repository元素的id相匹配。-->   <id>server001</id>   <!--鉴权用户名。鉴权用户名和鉴权密码表示服务器认证所需要的登录名和密码。 -->   <username>my_login</username>   <!--鉴权密码 。鉴权用户名和鉴权密码表示服务器认证所需要的登录名和密码。密码加密功能已被添加到2.1.0 +。详情请访问密码加密页面-->   <password>my_password</password>   <!--鉴权时使用的私钥位置。和前两个元素类似,私钥位置和私钥密码指定了一个私钥的路径(默认是${user.home}/.ssh/id_dsa)以及如果需要的话,一个密语。将来passphrase和password元素可能会被提取到外部,但目前它们必须在settings.xml文件以纯文本的形式声明。 -->   <privateKey>${usr.home}/.ssh/id_dsa</privateKey>   <!--鉴权时使用的私钥密码。-->   <passphrase>some_passphrase</passphrase>   <!--文件被创建时的权限。如果在部署的时候会创建一个仓库文件或者目录,这时候就可以使用权限(permission)。这两个元素合法的值是一个三位数字,其对应了unix文件系统的权限,如664,或者775。 -->   <filePermissions>664</filePermissions>   <!--目录被创建时的权限。 -->   <directoryPermissions>775</directoryPermissions>  </server> </servers>
复制代码

mirrors

复制代码
<!--为仓库列表配置的下载镜像列表。高级设置请参阅镜像设置页面 --> <mirrors>  <!--给定仓库的下载镜像。 -->  <mirror>   <!--该镜像的唯一标识符。id用来区分不同的mirror元素。 -->   <id>planetmirror.com</id>   <!--镜像名称 -->   <name>PlanetMirror Australia</name>   <!--该镜像的URL。构建系统会优先考虑使用该URL,而非使用默认的服务器URL。 -->   <url>http://downloads.planetmirror.com/pub/maven2</url>   <!--被镜像的服务器的id。例如,如果我们要设置了一个Maven中央仓库(http://repo.maven.apache.org/maven2/)的镜像,就需要将该元素设置成central。这必须和中央仓库的id central完全一致。-->   <mirrorOf>central</mirrorOf>  </mirror> </mirrors>
复制代码

profiles

复制代码
 <!--根据环境参数来调整构建配置的列表。settings.xml中的profile元素是pom.xml中profile元素的裁剪版本。它包含了id,activation, repositories, pluginRepositories和 properties元素。这里的profile元素只包含这五个子元素是因为这里只关心构建系统这个整体(这正是settings.xml文件的角色定位),而非单独的项目对象模型设置。如果一个settings中的profile被激活,它的值会覆盖任何其它定义在POM中或者profile.xml中的带有相同id的profile。 --> <profiles>  <!--根据环境参数来调整的构件的配置-->  <profile>   <!--该配置的唯一标识符。 -->   <id>test</id>
复制代码

Activation

复制代码
<!--自动触发profile的条件逻辑。Activation是profile的开启钥匙。如POM中的profile一样,profile的力量来自于它能够在某些特定的环境中自动使用某些特定的值;这些环境通过activation元素指定。activation元素并不是激活profile的唯一方式。settings.xml文件中的activeProfile元素可以包含profile的id。profile也可以通过在命令行,使用-P标记和逗号分隔的列表来显式的激活(如,-P test)。-->   <activation>    <!--profile默认是否激活的标识-->    <activeByDefault>false</activeByDefault>    <!--当匹配的jdk被检测到,profile被激活。例如,1.4激活JDK1.4,1.4.0_2,而!1.4激活所有版本不是以1.4开头的JDK。-->    <jdk>1.5</jdk>    <!--当匹配的操作系统属性被检测到,profile被激活。os元素可以定义一些操作系统相关的属性。-->    <os>     <!--激活profile的操作系统的名字 -->     <name>Windows XP</name>     <!--激活profile的操作系统所属家族(如 'windows')  -->     <family>Windows</family>     <!--激活profile的操作系统体系结构  -->     <arch>x86</arch>     <!--激活profile的操作系统版本-->     <version>5.1.2600</version>    </os>    <!--如果Maven检测到某一个属性(其值可以在POM中通过${name}引用),其拥有对应的name = 值,Profile就会被激活。如果值字段是空的,那么存在属性名称字段就会激活profile,否则按区分大小写方式匹配属性值字段-->    <property>     <!--激活profile的属性的名称-->     <name>mavenVersion</name>     <!--激活profile的属性的值 -->     <value>2.0.3</value>    </property>    <!--提供一个文件名,通过检测该文件的存在或不存在来激活profile。missing检查文件是否存在,如果不存在则激活profile。另一方面,exists则会检查文件是否存在,如果存在则激活profile。-->    <file>     <!--如果指定的文件存在,则激活profile。 -->     <exists>${basedir}/file2.properties</exists>     <!--如果指定的文件不存在,则激活profile。-->     <missing>${basedir}/file1.properties</missing>    </file>   </activation>
复制代码

Properties

复制代码
 <!--对应profile的扩展属性列表。Maven属性和Ant中的属性一样,可以用来存放一些值。这些值可以在POM中的任何地方使用标记${X}来使用,这里X是指属性的名称。属性有五种不同的形式,并且都能在settings.xml文件中访问。   1. env.X: 在一个变量前加上"env."的前缀,会返回一个shell环境变量。例如,"env.PATH"指代了$path环境变量(在Windows上是%PATH%)。   2. project.x:指代了POM中对应的元素值。例如: <project><version>1.0</version></project>通过${project.version}获得version的值。   3. settings.x: 指代了settings.xml中对应元素的值。例如:<settings><offline>false</offline></settings>通过 ${settings.offline}获得offline的值。   4. Java System Properties: 所有可通过java.lang.System.getProperties()访问的属性都能在POM中使用该形式访问,例如 ${java.home}。   5. x: 在<properties/>元素中,或者外部文件中设置,以${someVar}的形式使用。 -->   <properties>   <user.install>${user.home}/our-project</user.install>   </properties>note:如果该profile被激活,则可以再POM中使用${user.install}。
复制代码

Repositories

复制代码
  <!--远程仓库列表,它是Maven用来填充构建系统本地仓库所使用的一组远程项目。 -->   <repositories>    <!--包含需要连接到远程仓库的信息 -->    <repository>     <!--远程仓库唯一标识-->     <id>codehausSnapshots</id>     <!--远程仓库名称 -->     <name>Codehaus Snapshots</name>     <!--如何处理远程仓库里发布版本的下载-->     <releases>      <!--true或者false表示该仓库是否为下载某种类型构件(发布版,快照版)开启。  -->      <enabled>false</enabled>      <!--该元素指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳。这里的选项是:always(一直),daily(默认,每日),interval:X(这里X是以分钟为单位的时间间隔),或者never(从不)。 -->      <updatePolicy>always</updatePolicy>      <!--当Maven验证构件校验文件失败时该怎么做-ignore(忽略),fail(失败),或者warn(警告)。-->      <checksumPolicy>warn</checksumPolicy>     </releases>     <!--如何处理远程仓库里快照版本的下载。有了releases和snapshots这两组配置,POM就可以在每个单独的仓库中,为每种类型的构件采取不同的策略。例如,可能有人会决定只为开发目的开启对快照版本下载的支持。参见repositories/repository/releases元素-->     <snapshots>      <enabled/><updatePolicy/><checksumPolicy/>     </snapshots>     <!--远程仓库URL,按protocol://hostname/path形式 -->     <url>http://snapshots.maven.codehaus.org/maven2</url>     <!--用于定位和排序构件的仓库布局类型-可以是default(默认)或者legacy(遗留)。Maven 2为其仓库提供了一个默认的布局;然而,Maven 1.x有一种不同的布局。我们可以使用该元素指定布局是default(默认)还是legacy(遗留)。 -->     <layout>default</layout>    </repository>   </repositories>   <!--发现插件的远程仓库列表。仓库是两种主要构件的家。第一种构件被用作其它构件的依赖。这是中央仓库中存储的大部分构件类型。另外一种构件类型是插件。Maven插件是一种特殊类型的构件。由于这个原因,插件仓库独立于其它仓库。pluginRepositories元素的结构和repositories元素的结构类似。每个pluginRepository元素指定一个Maven可以用来寻找新插件的远程地址。-->   <pluginRepositories>    <!--包含需要连接到远程插件仓库的信息.参见profiles/profile/repositories/repository元素的说明-->          <pluginRepository>                <releases>            <enabled/><updatePolicy/><checksumPolicy/>     </releases>     <snapshots>      <enabled/><updatePolicy/><checksumPolicy/>     </snapshots>     <id/><name/><url/><layout/>          </pluginRepository>        </pluginRepositories>  </profile> </profiles>
复制代码

activeProfiles

复制代码
<!--手动激活profiles的列表,按照profile被应用的顺序定义activeProfile。 该元素包含了一组activeProfile元素,每个activeProfile都含有一个profile id。任何在activeProfile中定义的profile id,不论环境设置如何,其对应的        profile都会被激活。如果没有匹配的profile,则什么都不会发生。例如,env-test是一个activeProfile,则在pom.xml(或者profile.xml)中对应id的profile会被激活。如果运行过程中找不到这样一个profile,Maven则会像往常一样运行。 -->   <activeProfiles>    <!-- -->    <activeProfile>env-test</activeProfile>   </activeProfiles></settings>


说明:

1、使用-选项时,和后面的参数之间可以不要空格。而使用--选项时,和后面的参数之    间必须有空格。如下面的例子:

 $ mvn help:describe -Dcmd=compiler:compile

 $ mvn install --define maven.test.skip=true

2、有些命令行选项是从Maven2.1才有的。

3、更多命令行选项请查看mvn -h

 

定义属性

-D,--define<arg> 定义系统属性

这是最常用到的定制Maven插件行为的选项。

 

获得帮助

-h,--help  显示帮助信息

如果你要寻找特定插件的可用目标和参数信息,请参考Maven Help 插件。

 

使用构建剖面(profile)

要从命令行激活一个或多个构建剖面,使用下面的选项:

-P,--activate-profiles<arg> 被激活的,用逗号分隔的剖面列表

 

显示版本信息

要显示Maven版本信息,在命令行里,使用下面选项中的一个。

-V,--show-version 显示版本信息后继续执行Maven其他目标。

-v,--version 显示版本信息。

这两个选项输出相同的版本信息,但-v选项在打印版本信息后会中断Maven处理。如果你想让Maven版本信息出现在构建输出的开始处,你应该使用-V选项。如果你正在持续构建环境里运行Maven,并且你需要知道特定构建使用了哪个Maven版本,-V选项就可以派上用场。

 

离线模式运行

-o,--offline 离线模式工作

该参数可以阻止通过网络更新插件或依赖。

使用定制的POM或定制的Settings文件

如果你不喜欢pom.xml文件名、用户相关的Maven配置文件的位置或者全局配置文件的位置,你可以通过下面的选项定制这些参数。

-f, --file <file> 强制使用备用的POM文件

-s,--settings <arg> 用户配置文件的备用路径

-gs, --global-settings <file> 全局配置文件的备用路径

 

加密密码

下面的命令允许你使用Maven加密密码,然后存储到Maven settings文件里:

-emp,--encrypt-master-password <password> 加密主安全密码

-ep,--encrypt-password <password>  加密服务器密码

 

失败处理

下面的选项控制,在多模块项目构建的中间阶段,Maven如何应对构建失败。

-fae, --fail-at-end 仅影响构建结果,允许不受影响的构建继续

-ff, --fail-fast 遇到构建失败就停下来

-fn,--fail-never 无论项目结果如何,构建从不失败

-fn 和 -fae选项对于使用持续集成工具(例如Hunson)的多模块构建非常有用。 -ff 选项对于运行交互构建的开发者非常有用,因为开发者在开发周期中想得到快速的反馈。

 

控制Maven的日志级别

如果你想控制Maven的日志级别,你可以使用下面三个命令行选项:

-e, --errors 产生执行错误相关消息

-X, --debug 产生执行调试信息

-q, --quiet 仅仅显示错误

只有出现错误或问题,-q 选项才打印一条消息。-X 选项会打印大量的调试日志消息,这个选项主要被Maven开发者和Maven插件开发者用来诊断在开发过程中碰到的Maven代码问题。如果你想诊断依赖或路径问题,-X 选项也非常有用。如果你是Maven开发者,或者你需要诊断Maven插件的一个错误,那么-e选项就会派上用场。如果你想报告Maven或Maven插件的一个未预料到的问题,你应该传递-X 和 -e命令行选项。

用批处理方式运行Maven

要在批处理模式下运行Maven,使用下面的选项:

-B, --batch-mode 在非交互(批处理)模式下运行

如果你需要在非交互、持续集成环境下运行Manve,必须要使用批处理模式。在非交互模式下运行,当Mven需要输入时,它不会停下来接受用户的输入,而是使用合理的默认值。

 

下载和验证依赖

下面的命令行选项会影响Maven和远程仓库的交互以及Maven如何验证下载的构件:

-C, --strict-checksums 如果校验码不匹配的话,构建失败

-c, --lax-checksums 如果校验码不匹配的话,产生告警

-U, --update-snapshots 在远程仓管更新发布版本或快照版本时,强制更新。

如果你关注安全,你就想带 -C选项运行Maven。Maven仓库为每个存储在仓库里的构件维护一个MD5 和 SHA1 校验码。如果构件的校验码不匹配下载的构件,Maven默认被配置成告警终端用户。如果传递-C 选项,当遇到带着错误校验码的构件,会引起Maven构建失败。如果你想确保Maven检查所有快照依赖的最新版本,-U选项非常有用。

 

控制插件更新

下面的命令行选项告诉Maven,它将如何从远程仓库更新(或不更新)Maven插件:

-npu,--no-plugin-updates 对任何相关的注册插件,不进行最新检查。使用该选项使Maven表现出稳定行为,该稳定行为基于本地仓库当前可用的所有插件版本。

-cpu, --check-plugin-updates 对任何相关的注册插件,强制进行最新检查。强制Maven检查Maven插件的最新发布版本,即使在你的项目POM里明确规定了Maven插件版本,还是会强制更新。

-up, --update-plugins cpu的同义词.

下面的命令行选项影响Maven从远处仓库下载插件的方式:

-npr, --no-plugin-registry 对插件版本不使用~/.m2/plugin-registry.xml  里的配置。

-npr 命令行选项告诉Maven不要参考插件注册表。欲了解关于插件注册表的更多信息,去这里:http://maven.apache.org/guides/introduction/introduction-to-plugin-registry.html.


Maven内置变量说明:

  • ${basedir} 项目根目录(即pom.xml文件所在目录)
  • ${project.build.directory} 构建目录,缺省为target目录
  • ${project.build.outputDirectory} 构建过程输出目录,缺省为target/classes
  • ${project.build.finalName} 产出物名称,缺省为${project.artifactId}-${project.version}
  • ${project.packaging} 打包类型,缺省为jar
  • ${project.xxx} 当前pom文件的任意节点的内容
  • ${env.xxx} 获取系统环境变量。例如,"env.PATH"指代了$path环境变量(在Windows上是%PATH%)。
  • ${settings.xxx} 指代了settings.xml中对应元素的值。例如:<settings><offline>false</offline></settings>通过 ${settings.offline}获得offline的值。
  • Java System Properties: 所有可通过java.lang.System.getProperties()访问的属性都能在POM中使用,例如 ${JAVA_HOME}。


坐标是Maven最基本的概念,它就像每个构件的身份证号码,有了它我们就可以在数以千万计的构件中定位任何一个我们感兴趣的构件。举个最简单的例子,如果没有坐标,使用JUnit的时候,用户就需要去下载依赖jar包,用依赖的方式,简单配置使用如junit:junit:4.8.2就可以了。这里第一个junit是groupId,第二个junit是artifactId,4.8.2是version。

Maven的很多其他核心机制都依赖于坐标,其中最显著的就是仓库和依赖管理。对于仓库来说,有了坐标就知道在什么位置存储构件的内容,例如junit:junit:4.8.2就对应仓库中的路径/junit/junit/4.8.2/junit-4.8.2.pom/junit/junit/4.8.2/junit-4.8.2.jar这样的文件,读者可以直接访问中央仓库地址看到这样的仓库布局,或者浏览本地仓库目录~/.m2/repository/以获得直观的体验。

依赖的配置也是完全基于坐标的.

有了正确的坐标,Maven才能够在正确的位置找到依赖文件并使用,这里值为test的scope是用来控制该依赖只在测试时可用,与坐标无关。

正因为坐标是Maven核心的核心,因此规划正确的坐标至关重要,如果你使用了模糊不清的坐标,那么你的用户就很难找到你的构件,或者即使找到了,也容易写错。错误的使用坐标,还会造成冲突,如果你也使用junit这样的groupId,那会发生什么

 

Maven 坐标有groupId,artifactId,packaging,version,classifier

<groupId>com.x</groupId>  <artifactId>helloworld-1</artifactId>  <packaging>jar</packaging>  <version>0.0.1-SNAPSHOT</version>  

(1).groupId,定义当前maven项目隶属的实际项目。首先,maven项目和实际项目不一定是一对一的关系。比如SpringFramework这一实际项目,其对应的maven项目会有很  多,如: spring-core,spring-context等。这是由于maven中模块的概念,因此,一个实际项目往往会被划分成很多模块。其次,groupId不应该对应项目隶属的组织或公司。原因很简单,一个组织下会有很多个实际项目,如果groupId只定义到组织级别,而后面我们会看到,artifactId只能定义maven项目(模块),那么实际项目这个层将难以定义。最后,groupId的表示方式与java包名的表示方式类似,通常与域名反向一一对应。    

(2).artifactId,该元素定义实际项目中的一个maven项目(模块),推荐的做法是使用实际项目名称作为artifactId前缀,这样做的好处是方便寻找实际构件。在默认情况下,maven生成的构件,其文件名会以artifactId作为开头,如:helloworld-1-0.0.1-SNAPSHOT.jar,使用实际项目名称作为前缀之后,就能方便从一个lib文件夹中找到某个项目的一组构件。。

(3).version,该元素定义maven项目当前所处的版本,如:helloworld-1-0.0.1-SNAPSHOT.jar的版本是0.0.1。需要注意的是,maven定义了一套完整的版本规范,以及快照(SNAPSHOT)的概念。

(4).packaging, 定义了maven项目的打包方式。默认值为jar,可取值:ejb / ejb3 /jar / par / rar / war

(5).classifier,该元素用来帮助定义构建输出的一些附属构件。附属构件与主构件对应,如上例中的主构件是: nexus-indexer-2.0.0.jar,该项目可能还会通过使用一些插件生成如:helloworld-1-0.0.1-SNAPSHOT-javadoc.jar、helloworld-1-0.0.1-SNAPSHOT-sources.jar这样一些附属构件,其包含了java文档和源代码。这时候,javadoc和sources就是这两个附属构件的classifier。这样,附属构件也就拥有了自己唯一的坐标。

 项目构件的文件名是与坐标相对应, 规则为: artifactId-version[-classifier].packaging,[-classifier]为可选。


<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/maven-v4_0_0.xsd">      <modelVersion>4.0.0</modelVersion>      <groupId>com.x</groupId>      <artifactId>helloworld</artifactId>      <packaging>war</packaging>      <version>0.0.1-SNAPSHOT</version>      <name>helloworld Maven Webapp</name>            <properties>          <spring>3.0.5.RELEASE</spring>      </properties>            <dependencies>          <dependency>              <groupId>junit</groupId>              <artifactId>junit</artifactId>              <version>3.8.1</version>              <scope>test</scope>          </dependency>          <dependency>              <groupId>org.springframework</groupId>              <artifactId>spring-core</artifactId>              <version>${spring}</version>          </dependency>      </dependencies>  </project>  
复制代码

dependencies节点可以包含一个或多个dependency元素,以声明一个或多个项目依赖。

每个依赖可以包含的元素有:
groupId,artifactId和version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,maven根据坐标才能找到需要的依赖。
type:依赖的类型,对于项目坐标定义的packaging,默认值为jar。
scope:依赖范围。
optional:标记依赖是否可选。
exclusions:用来排除传递性依赖

 

*scope依赖范围

maven在编译项目主代码的时候需要使用一套classpath。假如,在编译项目主代码的时候需要用到spring-core,该文件以依赖的方式被引入到classpath中。其次,maven在编译和执行测试代码的时候会使用另外一套classpath。如:JUnit就是一个很好的例子,该文件也以依赖的方式引入到测试使用的classpath中,不同的是这里的依赖范围是test。最后,实际运行maven项目的时候,又会使用一套classpath。

依赖范围就是用来控制依赖与这三种classpath(编译classpath,测试classpath,运行classpath)的关系,maven有以下几种依赖范围:

1.compile :编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的maven依赖,对于编译、测试、运行三种classpath都有效。典型的例子如项目依赖spring。

2.test :测试依赖范围。使用此依赖范围的maven依赖,只对于测试classpath有效,在编译主代码或者运行项目时将无法使用此类依赖。典型的例子是:JUnit,它只有在编译测试代码及运行测试的时候才需要。

3.provided :  已提供依赖范围。使用此依赖范围的maven依赖,对于编译和测试classpath有效,但在运行时无效。典型的例子是:servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要maven重复地引入一遍。

4.runtime:运行时依赖范围。使用此依赖范围的maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。

5.system: 系统依赖范围。该依赖与三种classpath的关系,和provided依赖范围完全一致。但是,使用system范围的依赖时必须通过systemPath元素显式地指定依赖文件的路径。

复制代码
<dependency>        <groupId>javax.sql</groupId>        <artifactId>jdbc-stdext</artifactId>        <version>2.0</version>        <scope>system</scope>        <systemPath>${java.home}/lib/rt.jar</systemPath>    </dependency>    
复制代码

6.import:导入依赖范围。在依赖dependencyManagement下使用,作用是将目标的pom中dependencyManagement导入合并到当前pom的dependencyManagement元素中。

 

小结:

maven引入的传递性依赖机制,一方面大大简化和方便了依赖声明,另一方面,大部分情况下我们只需要关心项目的直接依赖是什么,而不用考虑这些直接依赖会引入什么传递性依赖。但有时候,当传递性依赖造成问题的时候,我们就需要清楚地知道该传递性依赖是从哪条依赖路径引入的。

例如,项目A有这样的依赖关系 : A-->B-->C-->X(1.0)、A-->D-->X(2.0),X是A的传递性依赖,但是两条依赖路径上有两个版 本的X,那么哪个X会被maven解析使用呢?两个版本都被解析显然是不对的,因为那会造成依赖重复,因此必须选择一个。maven依赖调解的第一原则:路径最近者优先。该例中X(1.0)的路径长度为3,而X(2.0)的路径长度为2,因此X(2.0)会被解析使用。

依赖调解第一原则不能解决所有问题,比如这样的依赖关系:A-->B-->Y(1.0),A-->C-->Y(2.0),Y(1.0)和Y(2.0)的依赖路径长度是一样的,都为2。那么到底谁会被解析使用呢?在maven2.0.8及之前的版本中,这是不确定的,但是maven2.0.9开始,为了尽可能避免构建的不确定性,maven定义了依赖调解的第二原则:第一声明者优先。在依赖路径长度相等的前提下,在POM中依赖声明的顺序决定了谁会被解析使用。顺序最靠前的那个依赖优胜。



* Maven仓库

         在项目开发中,  项目目录下往往会有一个lib目录,用来存放第三方依赖jar文件, 如spring log4j jar等文件,

         Maven仓库就是放置JAR文件(WAR,ZIP,POM等等)的地方,所有Maven项目可以从同一个Maven仓库中获取自己所需要的依赖JAR,节省了磁盘资源,

         也节省了时间 不用拷来拷去的。

         此外,由于Maven仓库中所有的JAR都有其自己的坐标,该坐标告诉Maven它的组ID,构件ID,版本,打包方式等等,因此Maven项目可以方便的进行依赖版本管理。

         你也不在需要提交JAR文件到SCM仓库中,你可以建立一个组织层次的Maven仓库,供所有成员使用。

* 仓库分类

在运行Maven的时,Maven所需要的依赖构件都是直接从本地仓库获取的,如果本地仓库有依赖构建,直接使用;

如果本地仓库没有,它会首先尝试从远程仓库下载构件至本地仓库,然后再使用本地仓库的构件。

* 本地仓库缺省地址在${user.home}/.m2/repository目录下,(例如:C:\Documents and Settings\Administrator\.m2\repository)

自定义本地仓库位置:

      配置进入maven/conf目录 编辑settings.xml文件 修改localRepository节点

 *中央仓库 是一个默认的远程仓库,  安装好Maven之后,我们可以建立一个简单的项目,配置一些简单的依赖,然后运行mvn clean install,项目就构建好了。我们没有手工的去下载任何jar文件,这一切都是因为Maven中央仓库的存在,当Maven在本地仓库找不到需要的jar文件时,它会查找远程仓库,而一个原始的Maven安装就自带了一个远程仓库——Maven中央仓库。 这个Maven中央仓库是在apache-maven3\lib\maven-model-builder-3.0.4.jar中定义,

  超级POM: \org\apache\maven\project\pom-4.0.0.xml

 *私服是一种特殊的远程仓库  为了节省宽带资源和时间 应该在局域网内架设一个私有的仓库服务器,私服代理广域网上的远程仓库, 供局域网内的Maven用户使用,

  当Maven需要下载构建的时候,先给私服仓库发出请求, 如果私服上不存在构建,则从外部的远程仓库下载,缓存到私服仓库中,再为maven的下载请求提供服务。

 

* 远程仓库配置

1.编辑项目pom文件

复制代码
<repositories>    <repository>      <id>maven-net-cn</id>      <name>Maven China Mirror</name>      <url>http://maven.net.cn/content/groups/public/</url>      <releases>        <enabled>true</enabled>      </releases>      <snapshots>        <enabled>false</enabled>      </snapshots>    </repository>  </repositories>  <pluginRepositories>    <pluginRepository>      <id>maven-net-cn</id>      <name>Maven China Mirror</name>      <url>http://maven.net.cn/content/groups/public/</url>      <releases>        <enabled>true</enabled>      </releases>      <snapshots>        <enabled>false</enabled>      </snapshots>        </pluginRepository>  </pluginRepositories>  
复制代码

 repositories节点下,可以有多个repository,每个repository都有一个唯一的ID,一个name,以及最重要的,远程仓库的url。

此外<releases><enabled>true</enabled></releases>告诉Maven可以从这个仓库下载releases版本的构件,而<snapshots><enabled>false</enabled></snapshots>告诉Maven不要从这个仓库下载snapshot版本的构件。

2.在settings.xml中配置全局的远程仓库  

在每个项目的pom中配置远程仓库 只是针对当前项目,  如果有10个项目  那就要配置10次  重复配置可以做到只配置一次,就是在settings.xml中做全局配置

复制代码
<settings>    ...    <profiles>      <profile>        <id>dev</id>        <!-- repositories and pluginRepositories here-->      </profile>    </profiles>    <activeProfiles>      <activeProfile>dev</activeProfile>    </activeProfiles>    ...  </settings>  
复制代码

 

* 远程仓库认证

编辑conf/settings.xml文件

复制代码
<servers>    <server>      <id>和pom文件中repository->id元素相同</id>      <privateKey>/path/to/private/key</privateKey>      <passphrase>optional; leave empty if not used.</passphrase>    </server>  </servers>  
复制代码

server元素的id必须和pom中需要认证的repository元素完全一直。

 

* 构建部署至远程仓库

  mvn install 会将项目生成的构件安装到本地Maven仓库,mvn deploy 用来将项目生成的构件分发到远程Maven仓库。

本地Maven仓库的构件只能供当前用户使用,在分发到远程Maven仓库之后,所有能访问该仓库的用户都能使用你的构件。

配置POM的distributionManagement来指定Maven的部署位置

复制代码
<project>      ...      <distributionManagement>        <repository>          <id>nexus-releases</id>          <name>Nexus Release Repository</name>          <url>http://127.0.0.1:8088/nexus/content/repositories/releases/</url>        </repository>        <snapshotRepository>          <id>nexus-snapshots</id>          <name>Nexus Snapshot Repository</name>          <url>http://127.0.0.1:8088/nexus/content/repositories/snapshots/</url>        </snapshotRepository>      </distributionManagement>      ...    </project>    
复制代码

Maven区别对待release版本的构件和snapshot版本的构件,snapshot为开发过程中的版本,实时,但不稳定,release版本则比较稳定。

Maven会根据你项目的版本来判断将构件分发到哪个仓库。

 一般来说,分发构件到远程仓库需要认证,如果你没有配置任何认证信息,你往往会得到401错误。这个时候,如下在settings.xml中配置认证信息:

复制代码
<settings>      ...      <servers>        <server>          <id>nexus-releases</id>          <username>username</username>          <password>password</password>        </server>        <server>          <id>nexus-snapshots</id>          <username>username</username>          <password>password</password>        </server>        </servers>      ...    </settings>  
复制代码

 

* 镜像

复制代码
<settings>  ...    <mirrors>      <mirror>        <id>maven-net-cn</id>        <name>Maven China Mirror</name>        <url>http://maven.net.cn/content/groups/public/</url>        <mirrorOf>central</mirrorOf>      </mirror>    </mirrors>  ...  </settings> 


*聚合(多模块)

             在一个项目中 往往有多个模块组成,例如有项目demo下面有a, b两个模块

             为了能使用一条命令就能构建demo-a, demo-b两个模块, 需要创建一个额外的聚合模块, 然后通过该模块构建整个项目的所有模块。

              聚合模块(demo-parent) pom:

复制代码
<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/maven-v4_0_0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.x.demo</groupId>    <artifactId>demo-parent</artifactId>    <packaging>pom</packaging>    <version>0.0.1-SNAPSHOT</version>    <name>demo-parent Maven Webapp</name>    <url>http://maven.apache.org</url>        <modules>      <module>../demo-a</module>      <module>../demo-b</module>    </modules>  </project>  
复制代码

模块a(demo-a) pom:

复制代码
<project xmlns="<a href="http://maven.apache.org/POM/4.0.0">http://maven.apache.org/POM/4.0.0</a>" xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>"    xsi:schemaLocation="<a href="http://maven.apache.org/POM/4.0.0">http://maven.apache.org/POM/4.0.0</a> <a href="http://maven.apache.org/maven-v4_0_0.xsd">http://maven.apache.org/maven-v4_0_0.xsd</a>">    <modelVersion>4.0.0</modelVersion>    <groupId>com.x.demo</groupId>    <artifactId>demo-a</artifactId>    <packaging>jar</packaging>    <version>0.0.1-SNAPSHOT</version>    <name>demo-a Maven Webapp</name>    <url>http://maven.apache.org</url>        <dependencies>      <dependency>        <groupId>junit</groupId>        <artifactId>junit</artifactId>        <version>3.8.1</version>        <scope>test</scope>      </dependency>    </dependencies>        <build>      <finalName>demo-a</finalName>    </build>  </project>  
复制代码

模块b(demo-b) pom:

复制代码
<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/maven-v4_0_0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.x.demo</groupId>    <artifactId>demo-b</artifactId>    <packaging>jar</packaging>    <version>0.0.1-SNAPSHOT</version>    <name>demo-b Maven Webapp</name>    <url>http://maven.apache.org</url>        <dependencies>      <dependency>        <groupId>junit</groupId>        <artifactId>junit</artifactId>        <version>3.8.1</version>        <scope>test</scope>      </dependency>    </dependencies>        <build>      <finalName>demo-b</finalName>    </build>  </project>  
复制代码

额外模块(demo-parent) pom中的modules节点有多个module,每个module的值都是一个被聚合模块的相对目录。

     关于聚合模块目录与其他模块的目录主要有两种形式:

      a.父子关系:

      

         父子关系  聚合模块的pom:

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

a.平行目录:

     

         平行目录  聚合模块的pom:

<modules>      <module>../demo-a</module>      <module>../demo-b</module>  </modules>  

最后在聚合模块(demo-parent)的pom上面 运行mvn命令 根据聚合顺序依次构建多个模块。

 

*继承

       上面的例子中, a,b两个模块都依赖junit, 为了消除重复,可以使用pom的继承,以达到一处声明,多处使用的目的。

      聚合模块(demo-parent) pom:

复制代码
<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/maven-v4_0_0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.x.demo</groupId>    <artifactId>demo-parent</artifactId>    <packaging>pom</packaging>    <version>0.0.1-SNAPSHOT</version>    <name>demo-parent Maven Webapp</name>    <url>http://maven.apache.org</url>         <dependencies>      <dependency>        <groupId>junit</groupId>        <artifactId>junit</artifactId>        <version>3.8.1</version>        <scope>test</scope>      </dependency>    </dependencies>     <modules>      <module>../demo-a</module>      <module>../demo-b</module>    </modules>  </project>  
复制代码

模块a(demo-a) pom:

复制代码
<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/maven-v4_0_0.xsd">    <modelVersion>4.0.0</modelVersion>        <parent>      <groupId>com.x.demo</groupId>      <artifactId>demo-parent</artifactId>      <version>0.0.1-SNAPSHOT</version>      <relativePath>../demo-parent/pom.xml</relativePath>    </parent>        <artifactId>demo-a</artifactId>    <name>demo-a Maven Webapp</name>        <build>      <finalName>demo-a</finalName>    </build>  </project>  
复制代码

模块b(demo-b) pom:

复制代码
<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/maven-v4_0_0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>      <groupId>com.x.demo</groupId>      <artifactId>demo-parent</artifactId>      <version>0.0.1-SNAPSHOT</version>      <relativePath>../demo-parent/pom.xml</relativePath>    </parent>        <artifactId>demo-b</artifactId>    <name>demo-a Maven Webapp</name>        <build>      <finalName>demo-b</finalName>    </build>  </project>  
复制代码

parent元素声明父模块,parent下的子节点groupId,artifactId,version指定父模块的坐标,这三个元素是必须的。

   节点relativePath指定父模块pom的路径,默认值是:../pom.xml,也就是说父pom在上一层目录,(<relativePath>../demo-parent/pom.xml</relativePath> 表示父模块pom和子模块是平行目录)

可以被继承的POM元素:

groupId:项目id,项目坐标的核心元素

version:项目版本,项目坐标的核心元素

description:项目描述信息

organization:项目组织信息

inceptionYear:项目创世年月

developers:项目开发者信息

contributors:项目贡献者信息

distributionManagement:项目部署配置

scm:项目的版本控制信息

mailingLists:项目邮件列表信息

properties:自定义的属性

dependencies:项目的依赖配置

dependencyManagement:项目的依赖管理配置

repositories:项目的仓库配置

build:项目源码目录配置。输出目录配置,插件配置等。

*依赖管理

             父模块(demo-parent) pom:

复制代码
<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/maven-v4_0_0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.x.demo</groupId>    <artifactId>demo-parent</artifactId>    <packaging>pom</packaging>    <version>0.0.1-SNAPSHOT</version>    <name>demo-parent Maven Webapp</name>    <url>http://maven.apache.org</url>        <!-- dependencyManagement 定义的依赖  需要在子pom中声明  不然不会产生效果 -->      <dependencyManagement>          <dependencies>          <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>3.8.1</version>            <scope>test</scope>          </dependency>      </dependencies>   </dependencyManagement>        <modules>      <module>../demo-a</module>      <module>../demo-b</module>    </modules>  </project>  
复制代码

     模块a(demo-a) pom:

复制代码
<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/maven-v4_0_0.xsd">    <modelVersion>4.0.0</modelVersion>        <parent>      <groupId>com.x.demo</groupId>      <artifactId>demo-parent</artifactId>      <version>0.0.1-SNAPSHOT</version>      <relativePath>../demo-parent/pom.xml</relativePath>    </parent>        <artifactId>demo-a</artifactId>    <name>demo-a Maven Webapp</name>      <properties>      <mail.version>1.4.1</mail.version>    </properties>         <dependencies>          <!-- 声明父pom中的依赖  这样才会真正被使用 -->          <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>          </dependency>                    <!-- 扩展依赖  父pom中并没有声明 不会影响到父POM 和其他模块 -->          <dependency>              <groupId>javax.mail</groupId>              <artifactId>mail</artifactId>              <version>${mail.version}</version>          </dependency>      </dependencies>          <build>      <finalName>demo-a</finalName>    </build>  </project>  
复制代码

模块b(demo-b) pom:

复制代码
<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/maven-v4_0_0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>      <groupId>com.x.demo</groupId>      <artifactId>demo-parent</artifactId>      <version>0.0.1-SNAPSHOT</version>      <relativePath>../demo-parent/pom.xml</relativePath>    </parent>        <artifactId>demo-b</artifactId>    <name>demo-a Maven Webapp</name>        <!-- 没有声明父pom中的依赖  不会被使用 -->        <build>      <finalName>demo-b</finalName>    </build>  </project>  
复制代码

父POM 中使用dependencyManagement 声明的依赖不会给子模块引入依赖, 只会继承这段配置。

在模块a(demo-a) pom中声明了父pom中junit依赖 在执行的时候才会获得真正的依赖信息。

模块b(demo-b) pom中没有声明父pom中junit依赖 不会产生实际效果


我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven-compiler-plugin完成的。进一步说,每个任务对应了一个插件目标(goal),每个插件会有一个或者多个目标,例如maven-compiler-plugin的compile目标用来编译位于src/main/java/目录下的主源码,testCompile目标用来编译位于src/test/java/目录下的测试源码。

用户可以通过两种方式调用Maven插件目标。第一种方式是将插件目标与生命周期阶段(lifecycle phase)绑定,这样用户在命令行只是输入生命周期阶段而已,例如Maven默认将maven-compiler-plugin的compile目标与compile生命周期阶段绑定,因此命令mvn compile实际上是先定位到compile这一生命周期阶段,然后再根据绑定关系调用maven-compiler-plugin的compile目标。第二种方式是直接在命令行指定要执行的插件目标,例如mvn archetype:generate 就表示调用maven-archetype-plugin的generate目标,这种带冒号的调用方式与生命周期无关。

认识上述Maven插件的基本概念能帮助你理解Maven的工作机制,不过要想更高效率地使用Maven,了解一些常用的插件还是很有必要的,这可以帮助你避免一不小心重新发明轮子。多年来Maven社区积累了大量的经验,并随之形成了一个成熟的插件生态圈。Maven官方有两个插件列表,第一个列表的GroupId为org.apache.maven.plugins,这里的插件最为成熟,具体地址为:http://maven.apache.org/plugins/index.html。第二个列表的GroupId为org.codehaus.mojo,这里的插件没有那么核心,但也有不少十分有用,其地址为:http://mojo.codehaus.org/plugins.html。

接下来笔者根据自己的经验介绍一些最常用的Maven插件,在不同的环境下它们各自都有其出色的表现,熟练地使用它们能让你的日常构建工作事半功倍。

maven-antrun-plugin

http://maven.apache.org/plugins/maven-antrun-plugin/

maven-antrun-plugin能让用户在Maven项目中运行Ant任务。用户可以直接在该插件的配置以Ant的方式编写Target,然后交给该插件的run目标去执行。在一些由Ant往Maven迁移的项目中,该插件尤其有用。此外当你发现需要编写一些自定义程度很高的任务,同时又觉得Maven不够灵活时,也可以以Ant的方式实现之。maven-antrun-plugin的run目标通常与生命周期绑定运行。

maven-archetype-plugin

http://maven.apache.org/archetype/maven-archetype-plugin/

Archtype指项目的骨架,Maven初学者最开始执行的Maven命令可能就是mvn archetype:generate,这实际上就是让maven-archetype-plugin生成一个很简单的项目骨架,帮助开发者快速上手。可能也有人看到一些文档写了mvn archetype:create,但实际上create目标已经被弃用了,取而代之的是generate目标,该目标使用交互式的方式提示用户输入必要的信息以创建项目,体验更好。maven-archetype-plugin还有一些其他目标帮助用户自己定义项目原型,例如你由一个产品需要交付给很多客户进行二次开发,你就可以为他们提供一个Archtype,帮助他们快速上手。

maven-assembly-plugin

http://maven.apache.org/plugins/maven-assembly-plugin/

maven-assembly-plugin的用途是制作项目分发包,该分发包可能包含了项目的可执行文件、源代码、readme、平台脚本等等。maven-assembly-plugin支持各种主流的格式如zip、tar.gz、jar和war等,具体打包哪些文件是高度可控的,例如用户可以按文件级别的粒度、文件集级别的粒度、模块级别的粒度、以及依赖级别的粒度控制打包,此外,包含和排除配置也是支持的。maven-assembly-plugin要求用户使用一个名为assembly.xml的元数据文件来表述打包,它的single目标可以直接在命令行调用,也可以被绑定至生命周期。

maven-dependency-plugin

http://maven.apache.org/plugins/maven-dependency-plugin/

maven-dependency-plugin最大的用途是帮助分析项目依赖,dependency:list能够列出项目最终解析到的依赖列表,dependency:tree能进一步的描绘项目依赖树,dependency:analyze可以告诉你项目依赖潜在的问题,如果你有直接使用到的却未声明的依赖,该目标就会发出警告。maven-dependency-plugin还有很多目标帮助你操作依赖文件,例如dependency:copy-dependencies能将项目依赖从本地Maven仓库复制到某个特定的文件夹下面。

maven-enforcer-plugin

http://maven.apache.org/plugins/maven-enforcer-plugin/

在一个稍大一点的组织或团队中,你无法保证所有成员都熟悉Maven,那他们做一些比较愚蠢的事情就会变得很正常,例如给项目引入了外部的SNAPSHOT依赖而导致构建不稳定,使用了一个与大家不一致的Maven版本而经常抱怨构建出现诡异问题。maven-enforcer-plugin能够帮助你避免之类问题,它允许你创建一系列规则强制大家遵守,包括设定Java版本、设定Maven版本、禁止某些依赖、禁止SNAPSHOT依赖。只要在一个父POM配置规则,然后让大家继承,当规则遭到破坏的时候,Maven就会报错。除了标准的规则之外,你还可以扩展该插件,编写自己的规则。maven-enforcer-plugin的enforce目标负责检查规则,它默认绑定到生命周期的validate阶段。

maven-help-plugin

http://maven.apache.org/plugins/maven-help-plugin/

maven-help-plugin是一个小巧的辅助工具,最简单的help:system可以打印所有可用的环境变量和Java系统属性。help:effective-pomhelp:effective-settings最为有用,它们分别打印项目的有效POM和有效settings,有效POM是指合并了所有父POM(包括Super POM)后的XML,当你不确定POM的某些信息从何而来时,就可以查看有效POM。有效settings同理,特别是当你发现自己配置的settings.xml没有生效时,就可以用help:effective-settings来验证。此外,maven-help-plugin的describe目标可以帮助你描述任何一个Maven插件的信息,还有all-profiles目标和active-profiles目标帮助查看项目的Profile。

maven-release-plugin

http://maven.apache.org/plugins/maven-release-plugin/

maven-release-plugin的用途是帮助自动化项目版本发布,它依赖于POM中的SCM信息。release:prepare用来准备版本发布,具体的工作包括检查是否有未提交代码、检查是否有SNAPSHOT依赖、升级项目的SNAPSHOT版本至RELEASE版本、为项目打标签等等。release:perform则是签出标签中的RELEASE源码,构建并发布。版本发布是非常琐碎的工作,它涉及了各种检查,而且由于该工作仅仅是偶尔需要,因此手动操作很容易遗漏一些细节,maven-release-plugin让该工作变得非常快速简便,不易出错。maven-release-plugin的各种目标通常直接在命令行调用,因为版本发布显然不是日常构建生命周期的一部分。

maven-resources-plugin

http://maven.apache.org/plugins/maven-resources-plugin/

为了使项目结构更为清晰,Maven区别对待Java代码文件和资源文件,maven-compiler-plugin用来编译Java代码,maven-resources-plugin则用来处理资源文件。默认的主资源文件目录是src/main/resources,很多用户会需要添加额外的资源文件目录,这个时候就可以通过配置maven-resources-plugin来实现。此外,资源文件过滤也是Maven的一大特性,你可以在资源文件中使用${propertyName}形式的Maven属性,然后配置maven-resources-plugin开启对资源文件的过滤,之后就可以针对不同环境通过命令行或者Profile传入属性的值,以实现更为灵活的构建。

maven-surefire-plugin

http://maven.apache.org/plugins/maven-surefire-plugin/

可能是由于历史的原因,Maven 2/3中用于执行测试的插件不是maven-test-plugin,而是maven-surefire-plugin。其实大部分时间内,只要你的测试类遵循通用的命令约定(以Test结尾、以TestCase结尾、或者以Test开头),就几乎不用知晓该插件的存在。然而在当你想要跳过测试、排除某些测试类、或者使用一些TestNG特性的时候,了解maven-surefire-plugin的一些配置选项就很有用了。例如 mvn test -Dtest=FooTest 这样一条命令的效果是仅运行FooTest测试类,这是通过控制maven-surefire-plugin的test参数实现的。

build-helper-maven-plugin

http://mojo.codehaus.org/build-helper-maven-plugin/

Maven默认只允许指定一个主Java代码目录和一个测试Java代码目录,虽然这其实是个应当尽量遵守的约定,但偶尔你还是会希望能够指定多个源码目录(例如为了应对遗留项目),build-helper-maven-plugin的add-source目标就是服务于这个目的,通常它被绑定到默认生命周期的generate-sources阶段以添加额外的源码目录。需要强调的是,这种做法还是不推荐的,因为它破坏了 Maven的约定,而且可能会遇到其他严格遵守约定的插件工具无法正确识别额外的源码目录。

build-helper-maven-plugin的另一个非常有用的目标是attach-artifact,使用该目标你可以以classifier的形式选取部分项目文件生成附属构件,并同时install到本地仓库,也可以deploy到远程仓库。

exec-maven-plugin

http://mojo.codehaus.org/exec-maven-plugin/

exec-maven-plugin很好理解,顾名思义,它能让你运行任何本地的系统程序,在某些特定情况下,运行一个Maven外部的程序可能就是最简单的问题解决方案,这就是exec:exec的用途,当然,该插件还允许你配置相关的程序运行参数。除了exec目标之外,exec-maven-plugin还提供了一个java目标,该目标要求你提供一个mainClass参数,然后它能够利用当前项目的依赖作为classpath,在同一个JVM中运行该mainClass。有时候,为了简单的演示一个命令行Java程序,你可以在POM中配置好exec-maven-plugin的相关运行参数,然后直接在命令运行 mvn exec:java 以查看运行效果。

jetty-maven-plugin

http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin

在进行Web开发的时候,打开浏览器对应用进行手动的测试几乎是无法避免的,这种测试方法通常就是将项目打包成war文件,然后部署到Web容器中,再启动容器进行验证,这显然十分耗时。为了帮助开发者节省时间,jetty-maven-plugin应运而生,它完全兼容 Maven项目的目录结构,能够周期性地检查源文件,一旦发现变更后自动更新到内置的Jetty Web容器中。做一些基本配置后(例如Web应用的contextPath和自动扫描变更的时间间隔),你只要执行 mvn jetty:run ,然后在IDE中修改代码,代码经IDE自动编译后产生变更,再由jetty-maven-plugin侦测到后更新至Jetty容器,这时你就可以直接测试Web页面了。需要注意的是,jetty-maven-plugin并不是宿主于Apache或Codehaus的官方插件,因此使用的时候需要额外的配置settings.xml的pluginGroups元素,将org.mortbay.jetty这个pluginGroup加入。

versions-maven-plugin

http://mojo.codehaus.org/versions-maven-plugin/

很多Maven用户遇到过这样一个问题,当项目包含大量模块的时候,为他们集体更新版本就变成一件烦人的事情,到底有没有自动化工具能帮助完成这件事情呢?(当然你可以使用sed之类的文本操作工具,不过不在本文讨论范围)答案是肯定的,versions-maven- plugin提供了很多目标帮助你管理Maven项目的各种版本信息。例如最常用的,命令 mvn versions:set -DnewVersion=1.1-SNAPSHOT 就能帮助你把所有模块的版本更新到1.1-SNAPSHOT。该插件还提供了其他一些很有用的目标,display-dependency- updates能告诉你项目依赖有哪些可用的更新;类似的display-plugin-updates能告诉你可用的插件更新;然后use- latest-versions能自动帮你将所有依赖升级到最新版本。最后,如果你对所做的更改满意,则可以使用 mvn versions:commit 提交,不满意的话也可以使用 mvn versions:revert 进行撤销。

 

举例

1、使用tomcat-maven-plugin插件自动化远程发布到Tomcat服务器

复制代码
<!-- 配置自动发布Tomcat插件(tomcat:redeploy) -->            <plugin>                <groupId>org.codehaus.mojo</groupId>                <artifactId>tomcat-maven-plugin</artifactId>                <configuration>                    <url>http://localhost:8080/manager/html</url>                    <username>zhoulumin</username>                    <password>19880627</password>                    <path>/sshe</path>                </configuration>            </plugin>
复制代码

 

2、使用cargo-maven2-plugin插件配置Tomcat本地自动发布(cargo:deploy)

复制代码
<!-- 通过cargo-maven2-plugin插件配置Tomcat自动发布(cargo:deploy) -->            <plugin>                <!-- 指定插件名称及版本号 -->                <groupId>org.codehaus.cargo</groupId>                <artifactId>cargo-maven2-plugin</artifactId>                <version>1.4.9</version>                <!-- 插件的Tomcat6.x配置 -->                <configuration>                    <wait>true</wait>        <!--是否说明,操作start、stop等后续操作必须等前面操作完成才能继续 -->                    <container>                <!-- 容器的配置 -->                        <containerId>tomcat6x</containerId>                        <!-- 指定tomcat版本 -->                        <type>installed</type>                                    <!-- 指定类型:standalone, installed等 -->                        <home>E:/zhoulumin/tools/fbrp-ide-32bit/apache-tomcat-6.0.35</home>    <!-- 指定Tomcat的位置,即catalina.home -->                    </container>                    <configuration>            <!-- 具体的配置 -->                        <type>existing</type>                                    <!-- 类型,existing:存在 -->                        <home>E:/zhoulumin/tools/fbrp-ide-32bit/apache-tomcat-6.0.35</home>    <!-- Tomcat的位置,即catalina.home -->                    </configuration>                    <deployables>    <!-- 部署设置 -->                        <deployable>    <!-- 部署的war包名等 -->                            <groupId>com.chowmin.sshe</groupId>                            <artifactId>sshe</artifactId>                            <type>war</type>                            <properties>                                <context>sshe</context>    <!-- 部署路径 -->                            </properties>                        </deployable>                    </deployables>                </configuration>                <executions>                    <!-- 执行的动作 -->                    <execution>                        <id>verify-deployer</id>                        <phase>install</phase>        <!-- 解析install -->                        <goals>                            <goal>deployer-deploy</goal>                        </goals>                    </execution>                    <execution>                        <id>clean-deployer</id>                        <phase>clean</phase>                        <goals>                            <goal>deployer-undeploy</goal>                        </goals>                    </execution>                </executions>            </plugin>
复制代码

 

3、使用cargo-maven2-plugin插件配置Tomcat远程自动发布(cargo:deploy)

复制代码
<!-- 通过cargo-maven2-plugin插件配置Tomcat自动发布(cargo:deploy) -->            <plugin>                <!-- 指定插件名称及版本号 -->                <groupId>org.codehaus.cargo</groupId>                <artifactId>cargo-maven2-plugin</artifactId>                <version>1.4.9</version>                <!-- 插件的Tomcat6.x配置 -->                <configuration>                    <wait>true</wait>        <!--是否说明,操作start、stop等后续操作必须等前面操作完成才能继续 -->                    <container>                <!-- 容器的配置 -->                        <containerId>tomcat6x</containerId>                        <!-- 指定tomcat版本 -->                        <type>remote</type>                                    <!-- 指定类型:standalone, installed等 -->                    </container>                    <configuration>            <!-- 具体的配置 -->                        <type>runtime</type>                                    <!-- 类型,existing:存在 -->                        <properties>                                            <!-- 配置属性 -->                            <cargo.tomcat.manager.url>http://localhost:8080/manager</cargo.tomcat.manager.url>        <!-- 管理地址 -->                            <cargo.remote.username>zhoulumin</cargo.remote.username>                                    <!-- Tomcat用户名 -->                            <cargo.remote.password>19880627</cargo.remote.password>                                    <!-- Tomcat密码 -->                            <cargo.tomcat.ajp.port>8009</cargo.tomcat.ajp.port>                                        <!-- Ajp端口 -->                        </properties>                    </configuration>                    <deployables>    <!-- 部署设置 -->                        <deployable>    <!-- 部署的war包名等 -->                            <groupId>com.chowmin.sshe</groupId>                            <artifactId>sshe</artifactId>                            <type>war</type>                            <properties>                                <context>sshe</context>    <!-- 部署路径 -->                            </properties>                        </deployable>                    </deployables>                </configuration>                <executions>                    <!-- 执行的动作 -->                    <execution>                        <id>verify-deployer</id>                        <phase>install</phase>        <!-- 解析install -->                        <goals>                            <goal>deployer-deploy</goal>                        </goals>                    </execution>                    <execution>                        <id>clean-deployer</id>                        <phase>clean</phase>                        <goals>                            <goal>deployer-undeploy</goal>                        </goals>                    </execution>                </executions>            </plugin>


“打包“这个词听起来比较土,比较正式的说法应该是”构建项目软件包“,具体说就是将项目中的各种文件,比如源代码、编译生成的字节码、配置文件、文档,按照规范的格式生成归档,最常见的当然就是JAR包和WAR包了,复杂点的例子是Maven官方下载页面的分发包,它有自定义的格式,方便用户直接解压后就在命令行使用。作为一款”打包工具“,Maven自然有义务帮助用户创建各种各样的包,规范的JAR包和WAR包自然不再话下,略微复杂的自定义打包格式也必须支持,本文就介绍一些常用的打包案例以及相关的实现方式,除了前面提到的一些包以外,你还能看到如何生成源码包、Javadoc包、以及从命令行可直接运行的CLI包。

Packaging的含义

任何一个Maven项目都需要定义POM元素packaging(如果不写则默认值为jar)。顾名思义,该元素决定了项目的打包方式。实际的情形中,如果你不声明该元素,Maven会帮你生成一个JAR包;如果你定义该元素的值为war,那你会得到一个WAR包;如果定义其值为POM(比如是一个父模块),那什么包都不会生成。除此之外,Maven默认还支持一些其他的流行打包格式,例如ejb3和ear。你不需要了解具体的打包细节,你所需要做的就是告诉Maven,”我是个什么类型的项目“,这就是约定优于配置的力量。

为了更好的理解Maven的默认打包方式,我们不妨来看看简单的声明背后发生了什么,对一个jar项目执行mvn package操作,会看到如下的输出:

[INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) @ git-demo ---[INFO] Building jar: /home/juven/git_juven/git-demo/target/git-demo-1.2-SNAPSHOT.jar

相比之下,对一个war项目执行mvn package操作,输出是这样的:

复制代码
复制代码
[INFO] --- maven-war-plugin:2.1:war (default-war) @ webapp-demo ---[INFO] Packaging webapp[INFO] Assembling webapp [webapp-demo] in [/home/juven/git_juven/webapp-demo/target/webapp-demo-1.0-SNAPSHOT][INFO] Processing war project[INFO] Copying webapp resources [/home/juven/git_juven/webapp-demo/src/main/webapp][INFO] Webapp assembled in [90 msecs][INFO] Building war: /home/juven/git_juven/webapp-demo/target/webapp-demo-1.0-SNAPSHOT.war
复制代码
复制代码

对应于同样的package生命周期阶段,Maven为jar项目调用了maven-jar-plugin,为war项目调用了maven-war-plugin,换言之,packaging直接影响Maven的构建生命周期。了解这一点非常重要,特别是当你需要自定义打包行为的时候,你就必须知道去配置哪个插件。一个常见的例子就是在打包war项目的时候排除某些web资源文件,这时就应该配置maven-war-plugin如下:

复制代码
复制代码
<plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-war-plugin</artifactId>    <version>2.1.1</version>    <configuration>      <webResources>        <resource>          <directory>src/main/webapp</directory>          <excludes>            <exclude>**/*.jpg</exclude>          </excludes>        </resource>      </webResources>    </configuration>  </plugin>
复制代码
复制代码

源码包和Javadoc包

一个Maven项目只生成一个主构件,当需要生成其他附属构件的时候,就需要用上classifier。源码包和Javadoc包就是附属构件的极佳例子。它们有着广泛的用途,尤其是源码包,当你使用一个第三方依赖的时候,有时候会希望在IDE中直接进入该依赖的源码查看其实现的细节,如果该依赖将源码包发布到了Maven仓库,那么像Eclipse就能通过m2eclipse插件解析下载源码包并关联到你的项目中,十分方便。由于生成源码包是极其常见的需求,因此Maven官方提供了一个插件来帮助用户完成这个任务:

复制代码
复制代码
<plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-source-plugin</artifactId>    <version>2.1.2</version>    <executions>      <execution>        <id>attach-sources</id>        <phase>verify</phase>        <goals>          <goal>jar-no-fork</goal>        </goals>      </execution>    </executions>  </plugin>
复制代码
复制代码

类似的,生成Javadoc包只需要配置插件如下:

复制代码
复制代码
  <plugin>              <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-javadoc-plugin</artifactId>    <version>2.7</version>    <executions>      <execution>        <id>attach-javadocs</id>          <goals>            <goal>jar</goal>          </goals>      </execution>    </executions>  </plugin>    
复制代码
复制代码

为了帮助所有Maven用户更方便的使用Maven中央库中海量的资源,中央仓库的维护者强制要求开源项目提交构件的时候同时提供源码包和Javadoc包。这是个很好的实践,读者也可以尝试在自己所处的公司内部实行,以促进不同项目之间的交流。

可执行CLI包

除了前面提到了常规JAR包、WAR包,源码包和Javadoc包,另一种常被用到的包是在命令行可直接运行的CLI(Command Line)包。默认Maven生成的JAR包只包含了编译生成的.class文件和项目资源文件,而要得到一个可以直接在命令行通过java命令运行的JAR文件,还要满足两个条件:

  • JAR包中的/META-INF/MANIFEST.MF元数据文件必须包含Main-Class信息。
  • 项目所有的依赖都必须在Classpath中。

Maven有好几个插件能帮助用户完成上述任务,不过用起来最方便的还是maven-shade-plugin,它可以让用户配置Main-Class的值,然后在打包的时候将值填入/META-INF/MANIFEST.MF文件。关于项目的依赖,它很聪明地将依赖JAR文件全部解压后,再将得到的.class文件连同当前项目的.class文件一起合并到最终的CLI包中,这样,在执行CLI JAR文件的时候,所有需要的类就都在Classpath中了。下面是一个配置样例:

复制代码
复制代码
  <plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-shade-plugin</artifactId>    <version>1.4</version>    <executions>      <execution>        <phase>package</phase>        <goals>          <goal>shade</goal>        </goals>        <configuration>          <transformers>            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">              <mainClass>com.juvenxu.mavenbook.HelloWorldCli</mainClass>            </transformer>          </transformers>        </configuration>      </execution>    </executions>  </plugin>
复制代码
复制代码

上述例子中的,我的Main-Class是com.juvenxu.mavenbook.HelloWorldCli,构建完成后,对应于一个常规的hello-world-1.0.jar文件,我还得到了一个hello-world-1.0-cli.jar文件。细心的读者可能已经注意到了,这里用的是cli这个classifier。最后,我可以通过java -jar hello-world-1.0-cli.jar命令运行程序。

自定义格式包

实际的软件项目常常会有更复杂的打包需求,例如我们可能需要为客户提供一份产品的分发包,这个包不仅仅包含项目的字节码文件,还得包含依赖以及相关脚本文件以方便客户解压后就能运行,此外分发包还得包含一些必要的文档。这时项目的源码目录结构大致是这样的:

复制代码
复制代码
pom.xmlsrc/main/java/src/main/resources/src/test/java/src/test/resources/src/main/scripts/src/main/assembly/README.txt
复制代码
复制代码

除了基本的pom.xml和一般Maven目录之外,这里还有一个src/main/scripts/目录,该目录会包含一些脚本文件如run.sh和run.bat,src/main/assembly/会包含一个assembly.xml,这是打包的描述文件,稍后介绍,最后的README.txt是份简单的文档。

我们希望最终生成一个zip格式的分发包,它包含如下的一个结构:

bin/lib/README.txt

其中bin/目录包含了可执行脚本run.sh和run.bat,lib/目录包含了项目JAR包和所有依赖JAR,README.txt就是前面提到的文档。

描述清楚需求后,我们就要搬出Maven最强大的打包插件:maven-assembly-plugin。它支持各种打包文件格式,包括zip、tar.gz、tar.bz2等等,通过一个打包描述文件(该例中是src/main/assembly.xml),它能够帮助用户选择具体打包哪些文件集合、依赖、模块、和甚至本地仓库文件,每个项的具体打包路径用户也能自由控制。如下就是对应上述需求的打包描述文件src/main/assembly.xml:

复制代码
复制代码
<assembly>  <id>bin</id>  <formats>    <format>zip</format>  </formats>  <dependencySets>    <dependencySet>      <useProjectArtifact>true</useProjectArtifact>      <outputDirectory>lib</outputDirectory>    </dependencySet>  </dependencySets>  <fileSets>    <fileSet>      <outputDirectory>/</outputDirectory>      <includes>        <include>README.txt</include>      </includes>    </fileSet>    <fileSet>      <directory>src/main/scripts</directory>      <outputDirectory>/bin</outputDirectory>      <includes>        <include>run.sh</include>        <include>run.bat</include>      </includes>    </fileSet>  </fileSets></assembly>
复制代码
复制代码
  • 首先这个assembly.xml文件的id对应了其最终生成文件的classifier。
  • 其次formats定义打包生成的文件格式,这里是zip。因此结合id我们会得到一个名为hello-world-1.0-bin.zip的文件。(假设artifactId为hello-world,version为1.0)
  • dependencySets用来定义选择依赖并定义最终打包到什么目录,这里我们声明的一个depenencySet默认包含所有所有依赖,而useProjectArtifact表示将项目本身生成的构件也包含在内,最终打包至输出包内的lib路径下(由outputDirectory指定)。
  • fileSets允许用户通过文件或目录的粒度来控制打包。这里的第一个fileSet打包README.txt文件至包的根目录下,第二个fileSet则将src/main/scripts下的run.sh和run.bat文件打包至输出包的bin目录下。

打包描述文件所支持的配置远超出本文所能覆盖的范围,为了避免读者被过多细节扰乱思维,这里不再展开,读者若有需要可以去参考这份文档。

最后,我们需要配置maven-assembly-plugin使用打包描述文件,并绑定生命周期阶段使其自动执行打包操作:

复制代码
复制代码
  <plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-assembly-plugin</artifactId>    <version>2.2.1</version>    <configuration>      <descriptors>        <descriptor>src/main/assembly/assembly.xml</descriptor>      </descriptors>    </configuration>    <executions>      <execution>        <id>make-assembly</id>        <phase>package</phase>        <goals>          <goal>single</goal>        </goals>      </execution>    </executions>  </plugin>
复制代码
复制代码

运行mvn clean package之后,我们就能在target/目录下得到名为hello-world-1.0-bin.zip的分发包了。

小结

打包是项目构建最重要的组成部分之一,本文介绍了主流Maven打包技巧,包括默认打包方式的原理、如何制作源码包和Javadoc包、如何制作命令行可运行的CLI包、以及进一步的,如何基于个性化需求自定义打包格式。这其中涉及了很多的Maven插件,当然最重要,也是最为复杂和强大的打包插件就是maven-assembly-plugin。事实上Maven本身的分发包就是通过maven-assembly-plugin制作的,感兴趣的读者可以直接查看源码一窥究竟。



原创粉丝点击