码迷,mamicode.com
首页 > 其他好文 > 详细

Maven学习笔记

时间:2016-09-04 10:11:19      阅读:206      评论:0      收藏:0      [点我收藏+]

标签:

1.Maven安装
Maven和ant同为apache出版的构建工具,与gradle是一类东西,与C语言中的make是同一类产品.从apache官网上下载maven的zip安装包,解压即可使用,需要把解压后的bin目录添加到环境变量中去.
Eclipse是自带maven的,如果不想使用eclipse的内置maven,可以在preference->maven->installations中进行设置.
2.最简的pom.xml文件
pom的意思是project object model项目对象模型

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.jenkov</groupId>
    <artifactId>java-web-crawler</artifactId>
    <version>1.0.0</version>
</project>

其中,modelVersion表示正在使用的pom模型版本,groupId表示项目名称,artifactId表示模块名称,一个项目可以包含多个模块.
3.pom的继承
一个pom可以继承自父pom,它可以继承父pom的dependencies,要想让一个pom继承另一个pom,可以使用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/xsd/maven-4.0.0.xsd”>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>my-parent</artifactId>
        <version>2.0</version>
        <relativePath>../my-parent</relativePath>
    </parent>
    <artifactId>my-project</artifactId>
    ...
</project>

子pom中的值会覆盖父pom中的值.因为pom的继承关系,最终的pom成为有效pom,可以通过mvn help:effective-pom命令来查看最终的pom.
每一个pom.xml默认继承super pom,super pom内容如下:

<project>
  <modelVersion>4.0.0</modelVersion>
  <name>Maven Default Project</name>
 
  <repositories>
    <repository>
      <id>central</id>
      <name>Maven Repository Switchboard</name>
      <layout>default</layout>
      <url>http://repo1.maven.org/maven2</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>
 
  <pluginRepositories>
    <pluginRepository>
      <id>central</id>
      <name>Maven Plugin Repository</name>
      <url>http://repo1.maven.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
    </pluginRepository>
  </pluginRepositories>
 
  <build>
    <directory>target</directory>
    <outputDirectory>target/classes</outputDirectory>
    <finalName>${artifactId}-${version}</finalName>
    <testOutputDirectory>target/test-classes</testOutputDirectory>
    <sourceDirectory>src/main/java</sourceDirectory>
    <scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
    <testSourceDirectory>src/test/java</testSourceDirectory>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>src/test/resources</directory>
      </testResource>
    </testResources>
  </build>
 
  <reporting>
    <outputDirectory>target/site</outputDirectory>
  </reporting>
 
  <profiles>
    <profile>
      <id>release-profile</id>
 
      <activation>
        <property>
          <name>performRelease</name>
        </property>
      </activation>
 
      <build>
        <plugins>
          <plugin>
            <inherited>true</inherited>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
 
            <executions>
              <execution>
                <id>attach-sources</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <inherited>true</inherited>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
 
            <executions>
              <execution>
                <id>attach-javadocs</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <inherited>true</inherited>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
 
            <configuration>
              <updateReleaseInfo>true</updateReleaseInfo>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
 
</project>

4.maven的配置
maven配置文件中的配置相当于全局配置,对于所有的pom.xml都是有效的.在配置文件settings.xml中可以配置:
-本地仓库的路径,默认为~/.m2
-当前编译选项
-其他一些配置
settings.xml有两个:一个是%Maven_Home%/conf/settings.xml,另一个是~/.m2/settings.xml.后者会覆盖前者的设置.
5.运行maven
maven构建项目有三个概念:生命周期,阶段,目标.maven内置三个生命周期,一个生命周期包括多个阶段,一个阶段包括多个目标.
运行maven只需要输入mvn命令,maven就会自动查找当前目录下的pom.xml并按照要求进行执行.
mvn命令还可以带一些参数,参数包括阶段和目标.
例如install就是一个阶段,它是在target目录中生成jar文件并将jar文件复制到maven本地仓库中去(即~/.m2目录中).执行install阶段就会默认把install之前的阶段全部执行,命令为mvn install
可以向mvn传递多个参数,表示执行多个阶段,例如mvn clean install,先进行clean把target中生成的jar删除,然后再执行install.
可以让mvn执行某个目标,命令形式为
mvn 阶段名:目标名
例如mvn dependencies:copy-dependencies
6.maven项目的目录结构
maven遵循”约定大于配置”原则,对目录有默认的组织,如果不按照默认的来,就需要指明src目录,target目录等.

- src
  - main
    - java
    - resources
    - webapp
  - test
    - java
    - resources

- target

target目录是maven创建的,执行mvn clean命令之后target目录被清空.

7.项目依赖
项目A依赖项目B,项目B依赖项目C.众多的项目形成一个有向无环图(DAG),每一个项目相当于一个结点,每一条有向边表示一个依赖关系.如果要使用B.jar,不下载C.jar肯定会报错.使用maven,就可以自动推导出项目所依赖的全部jar包,解决项目依赖问题是maven的重要作用之一.maven会自动下载所需jar包到本地仓库中,在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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jenkov.crawler</groupId>
    <artifactId>java-web-crawler</artifactId>
    <version>1.0.0</version>

    <dependencies>
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.7.1</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
    </build>
</project>

有的时候,指定的依赖在Maven的中央仓库里没有。你可以直接下载这些依赖,然后放到Maven的本地仓库。这些依赖必须放到与groupId、 artifactId和version匹配的子目录中。用/替换所有的点(.)并且使用/分隔groupId、artifactId和version,这就是与该依赖匹配的子目录。

上面示例中的两个依赖将会被放到以下子目录中:
MAVEN_REPOSITORY_ROOT/junit/junit/4.8.1
MAVEN_REPOSITORY_ROOT/org/jsoup/jsoup/1.7.1
Maven仓库分为三种:本地仓库(即~/.m2),远程仓库(自己建立的maven服务器),中心仓库(http://mvnrepository.com/).
8.外部依赖
有时只有一个jar包而没有它的groupId和artifactId,并且三种maven仓库中都没有这个jar包项目,但当前项目依赖这个jar包,这种依赖叫做外部依赖,可以用如下配置指定外部依赖.

<dependency>
  <groupId>mydependency</groupId>
  <artifactId>mydependency</artifactId>
  <scope>system</scope>
  <version>1.0</version>
  <systemPath>${basedir}\war\WEB-INF\lib\mydependency.jar</systemPath>
</dependency>

这种方式需要在每一个maven工程的pom.xml中这么写,这样岂不是十分麻烦.一种解决方案是把第三方jar包安装到本地maven仓库中去.
mvn install:install-file -Dfile= -DgroupId= -DartifactId= -Dversion= -Dpackaging=
在这个命令中,需要手动提供groupId,artifactId等,如果第三方jar包有相应的pom.xml可以使用如下命令:
mvn install:install-file -Dfile= -DpomFile=
9.快照依赖
快照依赖指的是那些还在开发中的依赖(jar包)。与其经常地更新版本号来获取最新版本,不如你直接依赖项目的快照版本。快照版本的每一个build版本都会被下载到本地仓库,即使该快照版本已经在本地仓库了。总是下载快照依赖可以确保本地仓库中的每一个build版本都是最新的。
在pom文件的最开头(设置groupId和artifactId的地方),在版本号后追加-SNAPSHOT,则告诉Maven你的项目是一个快照版本。如:

<version>1.0-SNAPSHOT</version>
可以看到加到版本号后的-SNAPSHOT。
在配置依赖时,在版本号后追加-SNAPSHOT表明依赖的是一个快照版本。如:

<dependency>
    <groupId>com.jenkov</groupId>
    <artifactId>java-web-crawler</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

追加在version后的-SNAPSHOT告诉Maven这是一个快照版本.
可以在Maven配置文件中设置快照版本下载的频率.
10.maven仓库
Maven仓库就是存储jar包和一些元数据信息的目录。其中的元数据即pom文件,描述了该jar包属于哪个项目,以及jar包所需的外部依赖。该元数据信息使得Maven可以递归地下载所有的依赖,直到整个依赖树都下载完毕并放到你的本地仓库中。查找依赖时,首先是本地仓库,然后是中央仓库,最后,如果pom文件中配置了远程仓库,则会去远程仓库中查找。
(1) 本地仓库
本地仓库默认路径为~/.m2,可以在%MAVEN_HOME%/conf/settings.xml中设置本地仓库路径
<settings>
  <localRepository>
    d:\data\java\products\maven\repository
  </localRepository>
</settings>
可以通过mvn install命令构建自己的项目并安装到本地仓库中去.
(2)中央仓库
Maven的中央仓库由Maven社区提供。默认情况下,所有不在本地仓库中的依赖都会去这个中央仓库查找。然后Maven会将这些依赖下载到你的本地仓库。访问中央仓库不需要做额外的配置。
(3)远程仓库
远程仓库是位于web服务器上的一个仓库,Maven可以从该仓库下载依赖,就像从中央仓库下载依赖一样。远程仓库可以位于Internet上的任何地方,也可以是位于本地网络中。
远程仓库一般用于放置组织内部的项目,该项目由多个项目共享。比如,由多个内部项目共用的安全项目。该安全项目不能被外部访问,因此不能放在公开的中央仓库下,而应该放到内部的远程仓库中。
远程仓库中的依赖也会被Maven下载到本地仓库中。
可以在pom文件里配置远程仓库。将以下的xml片段放到属性之后:

<repositories>
  <repository>
    <id>jenkov.code</id>
    <url>http://maven.jenkov.com/maven2/lib</url>
  </repository>
</repositories>
11. Maven插件
使用Maven插件,可以向构建过程添加自定义的动作。创建一个简单的Java类,该类继承一个特殊的Maven类,然后为项目创建一个pom文件。该插件应该位于其项目下。
12.maven构建生命周期,阶段,目标
(1)生命周期
Maven有三个内嵌的生命周期:
-default
-clean
-site
这三个生命周期是互不干扰的,default是默认生命周期,负责项目的编译和打包;clean是删除target目录中之前生成的.class和.jar等文件,site关注的是为项目生成文档,实际上site可以为项目生成一个网页式的文档.
一个生命周期包含多个构建阶段,每个构建阶段又包括一系列目标.
(2)构建阶段
每一个构建生命期被分为一系列的构建阶段,构建阶段又被分为构建目标。因此,整个构建过程由一系列的构建生命期、构建阶段和构建目标组成。
你可以执行一个构建生命期,如clean或site,一个构建阶段,如default生命期的install,或者一个构建目标,如dependency:copy-dependencies。注意:你不能直接执行default生命期,你需要指定default生命期中的一个构建阶段或者构建目标。
当你执行一个构建阶段时,所有在该构建阶段之前的构建阶段(根据标准构建顺序)都会被执行。因此,执行install阶段,意味着所有位于install阶段前的构建阶段都会被执行,然后才执行install阶段。
default生命期更多的关注于构建代码。由于你不能直接执行default生命期,你需要执行其中一个构建阶段或者构建目标。default生命期包含了相当多的构建阶段和目标,这里不会所有都介绍。最常用的构建阶段有:
构建阶段 描述
validate 验证项目的正确性,以及所有必需的信息都是否都存在。同时也会确认项目的依赖是否都下载完毕。
compile 编译项目的源代码
test 选择合适的单元测试框架,对编译后的源码执行测试;这些测试不需要代码被打包或者部署。
package 将编译后的代码以可分配的形式打包,如Jar包。
install 将项目打包后安装到本地仓库,可以作为其它项目的本地依赖。
deploy 将最终的包复制到远程仓库,与其它开发者和项目共享。
将构建阶段的名称作为参数传给mvn命令,就是执行该构建阶段,如:

mvn package
该示例执行package构建阶段,因此在Maven的构建阶段序列中所有位于该阶段之前的阶段也都会被执行。

如果标准的Maven构建阶段和目标无法满足项目的需要,可以创建Maven插件增加你需要的构建功能。
(3)构建目标
构建目标是Maven构建过程中最细化的步骤。一个目标可以与一个或多个构建阶段绑定,也可以不绑定。如果一个目标没有与任何构建阶段绑定,你只能将该目标的名称作为参数传递给mvn命令来执行它。如果一个目标绑定到多个构建阶段,该目标在绑定的构建阶段执行的同时被执行.

13. 传递性依赖
传递性依赖是Maven2.0的新特性。假设你的项目依赖于一个库,而这个库又依赖于其他库。你不必自己去找出所有这些依赖,你只需要加上你直接依赖的库,Maven会隐式的把这些库间接依赖的库也加入到你的项目中。这个特性是靠解析从远程仓库中获取的依赖库的项目文件实现的。一般的,这些项目的所有依赖都会加入到项目中,或者从父项目继承,或者通过传递性依赖。
传递性依赖的嵌套深度没有任何限制,只是在出现循环依赖时会报错。
传递性依赖会导致包含库的依赖图增长的非常大。为了解决这个问题,Maven也提供了额外的机制,能让你指定哪些依赖会被包含:
依赖调解 – 当项目中出现多个版本构件依赖的情形,依赖调解决定最终应该使用哪个版本。目前,Maven 2.0只支持“短路径优先”原则,意思是项目会选择依赖关系树中路径最短的版本作为依赖。当然,你也可以在项目POM文件中显式指定使用哪个版本。值得注意的是,在Maven2.0.8及之前的版本中,当两个版本的依赖路径长度一致时,哪个依赖会被使用是不确定的。不过从Maven 2.0.9开始,POM中依赖声明的顺序决定了哪个版本会被使用,也叫作”第一声明原则”。
“短路径优先”意味着项目依赖关系树中路径最短的版本会被使用。例如,假设A、B、C之间的依赖关系是A->B->C->D(2.0)和A->E->(D1.0),那么D(1.0)会被使用,因为A通过E到D的路径更短。但如果你想要强制使用D(2.0),那你也可以在A中显式声明对D(2.0)的依赖。
依赖管理 – 在出现传递性依赖或者没有指定版本时,项目作者可以通过依赖管理直接指定模块版本。之前的章节说过,由于传递性依赖,尽管某个依赖没有被A直接指定,但也会被引入。相反的,A也可以将D加入<dependencyManagement>元素中,并在D可能被引用时决定D的版本号。
依赖范围 – 你可以指定只在当前编译范围内包含合适的依赖。
排除依赖 – 如果项目X依赖于项目Y,项目Y又依赖项目Z,项目X的所有者可以使用”exclusion”元素来显式排除项目Z。
可选依赖 – 如果项目Y依赖项目Z,项目Y的所有者可以使用”optional”元素来指定项目Z作为X的可选依赖。那么当项目X依赖项目Y时,X只依赖Y并不依赖Y的可选依赖Z。项目X的所有者也可以根据自己的意愿显式指定X对Z的依赖。(你可以把可选依赖理解为默认排除)。
下面对依赖范围进行详细说明.
依赖范围会影响传递性依赖,同时也会影响项目构建任务中使用的classpath。
Maven有以下6种依赖范围:
compile
这是默认范围。如果没有指定,就会使用该依赖范围。编译依赖对项目所有的classpath都可用。此外,编译依赖会传递到依赖的项目。
provided
和compile范围很类似,但provided范围表明你希望由JDK或者某个容器提供运行时依赖。例如,当使用Java EE构建一个web应用时,你会设置对Servlet API和相关的Java EE APIs的依赖范围为provided,因为web容器提供了运行时的依赖。provided依赖只对编译和测试classpath有效,并且不能传递。
runtime
runtime范围表明编译时不需要依赖,而只在运行时依赖。此依赖范围对运行和测试classpath有效,对编译classpath无效。
test
test范围表明使用此依赖范围的依赖,只在编译测试代码和运行测试的时候需要,应用的正常运行不需要此类依赖。
system
系统范围与provided类似,不过你必须显式指定一个本地系统路径的JAR,此类依赖应该一直有效,Maven也不会去仓库中寻找它。
import(Maven2.0.9及以上)
import范围只适用于pom文件中的<dependencyManagement>部分。表明指定的POM必须使用<dependencyManagement>部分的依赖。因为依赖已经被替换,所以使用import范围的依赖并不影响依赖传递。

Maven学习笔记

标签:

原文地址:http://www.cnblogs.com/weidiao/p/5838655.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!