【轉】Maven

 

第一章 介绍

Maven2 是一种项目管理框架,能够简化项目的开发,形成统一的规范,节省操作时间。

Maven2 是规范的开发流程、软件开发的约定、项目管理框架、构建工具。

Maven2 对项目进行了抽象,用 POM 描述。

Maven2 能够提供一致性、过程重用、敏捷性、可维护性。

1. Maven2 的原则:

1.1 配置管理的约定

项目目录的标准结构:利用维护人员的知识重用,节省时间

一个项目单个输出:利于模块化,利于按模块重用,当个目标输出,利用依赖管理来解决模块间的关联关系

命名约定:利于维护,输出一般为 <artifactId>-<version>.<extension>

1.2 构建逻辑重用

过程的执行均由 plug-in 进行,某个阶段对应一个 plug-in

1.3 根据声明执行

过程的执行通过在 POM 中的声明进行

1.4 一致的依赖管理

POM 中定义项目依赖。

对构建物的引用即为依赖, Maven 根据 POM 中定义的依赖从 respository 中查找依赖。 Respository 分为 localremote ,先查找 local 再查找 remote 。在依赖定义中的 <groupId><artifactId><version><extension> 与查找依赖项的关系: maven 会在 respositorygroupId/ artifactId/ version 目录中查找名为 <artifactId>-<version>.<extension> 的构建物。如果 groupIdcom.x..y.z ,则按照 java 包管理的方式对依赖项所在目录进行管理。

所有的项目,只要是依赖同一个构建物只在 respository 保存一份,并非按项目放在 lib 目录下。

 

第二章 安装与使用

1. 安装与配置

1.1 安装

a.      从网站下载 Maven2 ,解压即可

b.      在环境变量中添加 M2_HOME 指向解压后的目录

c.      PATH 中添加 $M2_HOME/bin

d.      在环境变量中添加 JAVA_HOME 指向 JDK 安装目录

e.      在命令行运行 mvn –-version 检查安装是否成功

1.2 配置

a.      命令行下运行 mvn installmvn compile ,会在用户的 home 目录下生成 .m2

b.      .m2 目录下新建文件 settings.xml 添加如下内容

<settings>

  <localRepository>D:\maven2_respository</localRepository> 

  <proxies>

   <proxy>

      <active>true</active>

      <protocol>http</protocol>

      <host>22.11.129.77</host>

      <port>8080</port>

      <username>lrs0669</username>

      <password>password01:</password>

      <nonProxyHosts>www.google.com|*.somewhere.com</nonProxyHosts>

    </proxy>

    <proxy>

      <active>true</active>

      <protocol>http</protocol>

      <host>22.1.227.85</host>

      <port>808</port>

      <username></username>

      <password></password>

      <nonProxyHosts>www.google.com|*.somewhere.com</nonProxyHosts>

    </proxy>

  </proxies>

</settings>

u        l ocalRepository 定义 local repository, 下载 jar 包所放的路径和执行项目的 install 命令所生成的构建输出放在 localRepository

u        如果通过代理服务器访问 remote respository ,代理服务器信息在 proxy 中定义,可以定 义多个

c.      在命令行下执行各个命令, maven2 会根据需要从互联网上下载所需要的 jar

2. 创建第一个 Maven 项目

使用 Maven 的原型机制创建一个项目, Maven 根据模版项目新建项目,原型项目包含了一个项目涉及到的所有方面。

mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-app

u        com.mycompany.app 为公司的开发的包结构前缀

u        my-app 为项目名称

3. Maven 命令

编译源代码 : 编译 src/main/java 下的源代码,将产生的 class 文件放在 target/classes

#mvn compile

 

编译单元测试:编译单元测试代码

#mvn test-compile

 

执行单元测试:

#mvn test

包括文件

  **/*Test.java

  **/Test*.java

  **/*TestCase.java

排除文件

  **/Abstract*Test.java

  **/Abstract*TestCase.java

 

打包:根据 pom.xml 的配置生成构建物

#mvn package

 

安装:执行构建,将输出物安装到 local respository 中,以便其他项目可以引用

#mvn install

 

清理:

#mvn clean

 

生成 eclipse 项目

#mvn elipse:eclipse

 

生成 IntelliJ IDEA 项目

#mvn idea:idea

 

生成项目网站

#mvn site

 

处理资源

#mvn process-resources

 

4. 处理资源

可以将资源打包到 jar 文件中 , 只需要在 src/main/resources 下放至需要打包的资源即可,建立相应的目录结构,资源会按照其在 resources 下的相对目录被打包到 jar 的根目录下。

Pom.xml 会打包到 jar 文件中,因此所有 Maven 项目都是自描述的,可以用 maven utils 来写 pom.xml ,对于读取则使用 java 的标准 api 读取 jar 包中的资源即可。

对于单元测试需要的资源处理方式类似,其对应目录为 src/test/resources 。可以使用如下方式读取资源文件 :

[...]

// Retrieve resource

InputStream is = getClass().getResourceAsStream( "/test.properties" );

// Do something with the resource

[...]

5. 对资源的过滤处理

有时资源文件中的某些值只有在构建时才能知道具体是什么值,比如 application.properties 中有变量 version ,则可以在其中如下定义

name=${project.name}

version=${project.version}

maven 会根据变量名在 pom.xml 中取相应的值,可通过 xml 元素的名来引用 pom.xml 中的值。

为使用这种过滤处理机制,需要在资源文件中以变量方式 ${property} 引用pom.xml ,用户的settings.xml 或者外部属性文件,系统属性中定义的变量。其次需要在pom.xml 中覆盖原来关于资源的默认定义,如下:

  <build>

  <resources>

  <resource>

  <directory>src/main/resources</directory>

  <filtering>true</filtering>

  </resource>

  </resources>

  </build>

可以使用命令:

#mvn process-resources

来对资源进行处理和过滤。执行这个命令后,资源会被复制到 target/classes 目录下,且进行了资源的过滤。

 

为使用定义在外部文件中的变量,可以按照如下的方式进行:

创建一个 properties 文件,如在 src/main/filters 下创建文件 filter.properties, 在其中定义变量 external.property=hello, i am from external file.

pom.xml 中增加对此文件的引用 :

  <build>

  <filters>

  <filter>src/main/filters/filter.properties</filter>

  </filters>

  <resources>

  <resource>

  <directory>src/main/resources</directory>

  <filtering>true</filtering>

  </resource>

  </resources>

  </build>

application.properties 加入对变量的引用:

external=${external.property}

 

如果不在外部属性文件中定义变量,可以在 pom.xmlproperties 节定义变量。

pom.xml 中添加 :

  <properties>

  <pom.property.welcome>

  You're welcome!

  </pom.property.welcome>

  </properties>

application.properties 加入对变量的引用:

pom.property=${pom.property.welcome}

 

maven 可以引用系统属性中定义的变量,包括 java 的系统属性或者命令行中用 -D 指定的 java 属性参数。

application.properties 加入对变量的引用:

java.version=${java.version}

command.line.pro=${command.line.pro}

在命令行执行:

#mvn process-resources "-Dcommand.line.pro=hello from command line"

 

6. 阻止过滤处理非文本文件

可能在资源目录中包含了图片等二进制文件,在过滤资源处理时需要将其派除在外,需要在过滤声明中包含 exclusion 排除相应资源,此外还需要增加一条不需要过滤处理的资源声明:

<project>

[...]

<build>

<resources>

<resource>

<directory>src/main/resources</directory>

<filtering>true</filtering>

<excludes>

<exclude>images/**</exclude>

</excludes>

</resource>

<resource>

<directory>src/main/resources</directory>

<includes>

<include>images/**</include>

</includes>

</resource>

</resources>

</build>

[...]

</project>

 

7. 使用 Maven Plus-In

可以使用 plus-in ,为使编译器允许 JDK5.0 源码,可以在 pom.xml 中加入:

<project>

[...]

<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>2.0</version>

<configuration>

<source>1.5</source>

<target>1.5</target>

</configuration>

</plugin>

</plugins>

</build>

[...]

</project>

可以注意到 plugindependency 非常类似,处理方式也类似,如果在本地没有则需要下载,如果本地有就直接使用。为了说明两者之间的相似性,在上例中明确给出了 groupIdversion ,但多数情况下并不需要。 groupId 默认会是 org.apache.maven.plugins 或者 org.codehaus.mojo 。如果不指定 version ,则会选择最新的版本。

为了解 plugin 的配置选项,可以使用命令:

#mvn help:describe –DgroupId=? -DartifactId=? 来查询,如

mvn help:describe -DgroupId=org.apache.maven.plugins -DartifactId=maven-compiler-plugin -Dfull=true

可以访问 http://maven.apache.org/plugins/ 来查询可用的 plugins

 


第三章 使用 Maven 创建应用

1 .介绍

通过一个项目 Proficio 来了解 Maven 的最佳实践、高级使用及 faq

2 .创建应用目录结构

为了重用,根据高聚合低耦合的方式按方面分解应用。

如下是应用的目录结构:

Proficio API: 应用的编程接口。

Proficio CLI :提供命令行接口的代码。

Proficio Core: 应用编程接口的实现。

Proficio Model: 应用的数据结构,包含需要的所有类。

Proficio Stores: 放置所有 store 模块,该应用包含 memory-based storeXStream-based store

Maven 使用默认的命名规则,你可以按照项目决定如何命名,唯一需要注意的就是项目成员能够轻易而一致的理解。

 

检查顶层的 pom ,可以看到应用 Proficio 的子模块,每个模块都是对一个 maven 工程的引用,对应一个 pom 。这种配置就是多模块构建,其 pom 如下:

<project>

<modelVersion>4.0.0</modelVersion>

<groupId>org.apache.maven.proficio</groupId>

<artifactId>proficio</artifactId>

<packaging>pom</packaging>

<version>1.0-SNAPSHOT</version>

<name>Maven Proficio</name>

<url>http://maven.apache.org</url>

[...]

<modules>

<module>proficio-model</module>

<module>proficio-api</module>

<module>proficio-core</module>

<module>proficio-stores</module>

<module>proficio-cli</module>

</modules>

[...]

</project>

注意其中的:

version 元素,其值为 1.0-SNAPSHOT ,在多模块应用中需要同时发布所有子模块,很有必要保持一致的应用版本。在顶层的 pom 中定义应用版本可以使所有模块使用。

Packaging 元素,其值为 pom ,在包含子模块的应用 pom 中,其值必须为 pom 。检查各个子模块对应项目的 pom 中的 Packaging 元素的值,除 Proficio Stores 其值为 pom ,其下包含两个子模块,其余均为 jar ,表明不再包含子模块。

Maven 以这样的方式递归的进行分析。

3 .使用项目继承

利用项目继承可以将结构信息,部署信息,共同的依赖信息放置在单一的位置。在每个工程的 pom 中:

[...]

<parent>

<groupId>org.apache.maven.proficio</groupId>

<artifactId>proficio</artifactId>

<version>1.0-SNAPSHOT</version>

</parent>

[...]

这使得项目的 pom 可以继承顶层 pom 中的定义,检查顶层 pomdependencies 部分:

<project>

[...]

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>3.8.1</version>

<scope>test</scope>

</dependency>

</dependencies>

[...]

</project>

在各个子模块的 pom 中没有对 Junit 依赖的定义,但是从顶层 pom 中继承了依赖的定义。

为了看清楚可以在一个子模块 pom 所在目录下,执行命令

#mvn help:effective-pom

可以看到最终起效果的 pom ,这在找错时很有效。

4 .管理依赖

pom 中指明 dependency management 元素的方式 maven 结合项目继承来管理依赖。在多模块应用中,可能多个子项目会有共同的依赖。此时为了正确运行,必须让所有的子项目使用依赖项的同一版本。必须确保应用的各个项目的依赖项和版本一致,才能保证测试的和发布的是相同的成果。因此,应在顶层的 pom 中定义共同的依赖关系。

Proficio 应用的顶层 pom 中的 dependency management 段如下:

  <dependencyManagement>

    <dependencies>

      <dependency>

        <groupId>com.devzuz.mvnbook.proficio</groupId>

        <artifactId>proficio-model</artifactId>

        <c>${project.version}</version>

      </dependency>

      <dependency>

        <groupId>com.devzuz.mvnbook.proficio</groupId>

        <artifactId>proficio-api</artifactId>

        <version>${project.version}</version>

      </dependency>

      <dependency>

        <groupId>com.devzuz.mvnbook.proficio</groupId>

        <artifactId>proficio-core</artifactId>

         <version>${project.version}</version>

      </dependency>

      <dependency>

        <groupId>com.devzuz.mvnbook.proficio</groupId>

        <artifactId>proficio-store-memory</artifactId>

        <version>${project.version}</version>

      </dependency>

      <dependency>

        <groupId>com.devzuz.mvnbook.proficio</groupId>

        <artifactId>proficio-store-xstream</artifactId>

        <version>${project.version}</version>

      </dependency>

      <dependency>

        <groupId>org.codehaus.plexus</groupId>

        <artifactId>plexus-container-default</artifactId>

        <version>1.0-alpha-9</version>

      </dependency>

    </dependencies>

  </dependencyManagement>

注意 ${project.version} 变量指的是应用的 version

顶层 pom 中的 dependenciesdependencyManagement 中的 dependencies 元素有一个重要的区别:

dependencyManagement 中的 dependencies 元素只表明依赖项版本的优先选择,并不影响项目的依赖项;而 dependencies 元素则影响项目的依赖项。

检查 Proficio api 模块的 pom:

<project>

  <parent>

    <groupId>com.devzuz.mvnbook.proficio</groupId>

    <artifactId>proficio</artifactId>

    <version>1.0-SNAPSHOT</version>

  </parent>

  <modelVersion>4.0.0</modelVersion>

  <artifactId>proficio-api</artifactId>

  <packaging>jar</packaging>

  <name>Proficio API</name>

  <dependencies>

    <dependency>

      <groupId>com.devzuz.mvnbook.proficio</groupId>

       <artifactId>proficio-model</artifactId>

    </dependency>

  </dependencies>

</project>

其中没有指明依赖项的版本信息,在顶层 pom 中的 dependencyManagement 中表明其优选的版本是 ${project.version}1.0-SNAPSHOT 。为使其模块 pom 完整,其版本信息会注入其中。只有当 dependencies 元素中没有指明版本信息时, dependencyManagement 中的 dependencies 元素才起作用。

5 .使用快照

当开发多模块应用时,每个模块时常变动。 Maven 的快照是由最新的源码构建的输出物。如果看一下顶层的 pom

<project>

[...]

<version>1.0-SNAPSHOT</version>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.apache.maven.proficio</groupId>

<artifactId>proficio-model</artifactId>

<version>${project.version}</version>

</dependency>

<dependency>

<groupId>org.apache.maven.proficio</groupId>

<artifactId>proficio-api</artifactId>

<version>${project.version}</version>

</dependency>

<dependency>

<groupId>org.codehaus.plexus</groupId>

<artifactId>plexus-container-default</artifactId>

<version>1.0-alpha-9</version>

</dependency>

</dependencies>

</dependencyManagement>

[...]

</project>

可以看到定义了一个快照版本 <version>1.0-SNAPSHOT</version>

将依赖项指定为快照版本, maven 会寻找依赖项的新版本,而不必手工指定新版本。 Maven 认为快照版本会进行变化,因此会更新它们。默认的 maven 会每日更新快照版本,可以使用命令行选项 -U 来进行强制更新。对于非快照版本, maven 会下载一次而不作更新。

6 .分析依赖冲突、使用版本区间

当项目变大时,不可避免的出现多个构建物对某个依赖项不同版本的依赖。 Maven 会选择离树顶最近的版本。这样会出现:

选择的依赖项的版本不具有其

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值