Maven(二)核心知识点

Maven有一些核心的知识点需要了解,比如坐标、仓库、插件、生命周期等概念,这里将依次解释。

坐标



Maven以构件来组成基本的控制单元,而定义这个构件的标示,Maven给定义为“坐标”。坐标是Maven最基本的概念,它就像每个构件的身份证号码,有了它我们就可以在数以千万计的构件中定位任何一个我们感兴趣的构件。

“坐标”这个词听起来很摸不着头脑,其实很简单,上一博客里面已经用到了,即下面这几个xml元素即组成了一个坐标

<groupId>com.company.maven01</groupId>
<artifactId>mavenapp1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

具体的每个元素代表什么意思请参考上一博客。

在用Maven开发一个项目时,是被强制要求定义改项目的坐标的。因为只有这样你的项目才会被其他项目引用,其他Maven项目才能使用你的项目生成出来的构件。比如上一博客中例子的dependency中引用了junit,可以看到里面实际上描述了所要引用junit的坐标。

下面举例说明几个常用的坐标,这些开发包可以直接加入到你的pom.xml的依赖中:

junit4.x

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

groovy

<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-all</artifactId>
    <version>2.2.2</version>
</dependency>

hibernate

 <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>3.6.10.Final</version>
</dependency> 

仓库



当你的Maven在本地安装好后实际上已经生成了一个本地仓库,可以在下列地址中找到

...\Users\username\.m2\repository

打开后发现里面全是各种本地仓库中的各种引用开发包,这里也能发现上一博客中已经引用的Junit,可以发现已经下载到本地仓库里面了

有本地仓库,那么是不是还有个远程仓库的概念呢?

答案是肯定的,这个远程仓库是个大仓库,叫做中央仓库,地址为

https://repo.maven.apache.org/maven2

有时候因为各种原因,可能你访问不了默认的中央仓库的地址,那么可以通过配置一个镜像中央仓库来解决

修改maven安装目录->conf文件夹->settings.xml这个文件,找到mirror这个元素,可以看到上面有一些注释:

 <!-- mirrors
   | This is a list of mirrors to be used in downloading artifacts from remote repositories.
   |
   | It works like this: a POM may declare a repository to use in resolving certain artifacts.
   | However, this repository may have problems with heavy traffic at times, so people have mirrored
   | it to several places.
   |
   | That repository definition will have a unique id, so we can create a mirror reference for that
   | repository, to be used as an alternate download site. The mirror site will be the preferred
   | server for that repository.
   |-->

大概的意思就是通过配置这个mirror元素可以替换掉默认的中央仓库,但是一旦配置了镜像中央仓库,原默认中央仓库则无法访问,除非将mirror元素归位

下面给出一个配置mirror的例子:

<mirror>
    <id>maven.net.cn</id>
    <mirrorOf>central</mirrorOf>
    <name>central mirror in china</name>
    <url>http://maven.net.cn/content/groups/public</url>
</mirror>

发布到本地仓库



现在你建立了一个项目 ,同时你有另一个项目B需要引用这个项目A,只要将项目A通过Maven发布到本地仓库即可

进入项目根目录,首先运行下mvn clean,这个命令将之前生成的target给一并清理了

D:\Work\moudle\maven\mavenapp1> ls target

    目录: D:\Work\moudle\maven\mavenapp1\target

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----          2015/8/4     15:05            classes
d----          2015/8/4     16:04            maven-archiver
d----          2015/8/4     15:05            maven-status
d----          2015/8/4     15:13            surefire-reports
d----          2015/8/4     15:13            test-classes
-a---          2015/8/4     16:04       2380 mavenapp1-1.0-SNAPSHOT.jar

D:\Work\moudle\maven\mavenapp1> mvn clean
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building mavenapp1 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ mavenapp1 ---
[INFO] Deleting D:\Work\moudle\maven\mavenapp1\target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.230 s
[INFO] Finished at: 2015-08-05T12:25:53+08:00
[INFO] Final Memory: 8M/184M
[INFO] ------------------------------------------------------------------------
D:\Work\moudle\maven\mavenapp1> ls

    目录: D:\Work\moudle\maven\mavenapp1

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----          2015/8/4     14:46            src
-a---          2015/8/4     14:46        784 pom.xml

发现target文件夹没了,随后再运行mvn install,即把改项目打包并发布到本地仓库:

D:\Work\moudle\maven\mavenapp1> mvn install
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building mavenapp1 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mavenapp1 ---
[INFO] Using ‘UTF-8‘ encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\Work\moudle\maven\mavenapp1\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ mavenapp1 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\Work\moudle\maven\mavenapp1\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mavenapp1 ---
[INFO] Using ‘UTF-8‘ encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\Work\moudle\maven\mavenapp1\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ mavenapp1 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\Work\moudle\maven\mavenapp1\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mavenapp1 ---
[INFO] Surefire report directory: D:\Work\moudle\maven\mavenapp1\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.company.maven01.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.007 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ mavenapp1 ---
[INFO] Building jar: D:\Work\moudle\maven\mavenapp1\target\mavenapp1-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ mavenapp1 ---
[INFO] Installing D:\Work\moudle\maven\mavenapp1\target\mavenapp1-1.0-SNAPSHOT.jar to D:\Users\haitao\.m
\company\maven01\mavenapp1\1.0-SNAPSHOT\mavenapp1-1.0-SNAPSHOT.jar
[INFO] Installing D:\Work\moudle\maven\mavenapp1\pom.xml to D:\Users\haitao\.m2\repository\com\company\m
\1.0-SNAPSHOT\mavenapp1-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10.977 s
[INFO] Finished at: 2015-08-05T12:27:50+08:00
[INFO] Final Memory: 21M/198M
[INFO] ------------------------------------------------------------------------

发现这个命令实际上是把编译、测试、打包等都给一起顺序跑了下,这个时候我们在看看本地仓库里面多了什么:

发现本地仓库以测试项目的包名建立了文件夹树,同时生成了jar文件,这个即为打包以后的jar。

那么下一步项目B该怎么引用项目A呢?是的,这里肯定又要用到坐标的概念了,即在项目B的描述文件pom.xml中添加项目A的依赖,并在dependency元素中写上项目A的坐标:

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.company.maven01</groupId>
      <artifactId>mavenapp1</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>jar</packaging>
    </dependency>
  </dependencies>

这样子再mvn compile项目B就没有问题了

仓库和坐标的关系



首先看看mavenapp1这个测试项目在本地仓库里面的目录结构

可以发现com\company\maven01恰好对应坐标中的groupId,随后的maven01正好对应artifactId,最后jar所处的1.0-SNAPSHOT正好对应了version。所以说有了坐标,就知道在什么位置存储构件的内容,中央仓库也是一个样,上述例子中引用的junit的可以把它的坐标描述为:junit:junit:3.8.1,在中央仓库地址中打开对应的目录果然看到了Junit的jar包

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

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

关于如何规划坐标内容的最佳实践,可以参考下面的经典博客:

http://www.infoq.com/cn/news/2010/12/xxb-maven-1

生命周期和插件



Maven定义了三套生命周期:clean、default、site,每个生命周期都包含了一些阶段(phase)。三套生命周期相互独立,但各个生命 周期中的phase却是有顺序的,且后面的phase依赖于前面的phase。执行某个phase时,其前面的phase会依顺序执行,但不会触发另外两 套生命周期中的任何phase。

  • clean,做些清理的工作
  • default,最核心的周期,做初始化和构建的工作,里面分的阶段很多,主要是compllie,test, package, install等
  • site,生成站点的周期,包括生成文档和发布等

Maven的生命周期是抽象的,实际需要插件来完成任务,这一过程是通过将插件的目标(goal)绑定到生命周期的具体阶段(phase)来完成的。这里就像设计模式中的模板模式,父类定义好了方法模板并规定对了执行顺序,而子类定义了每个模板方法具体要做的事情。这里的父类相当于maven,而子类就像是一个个的插件。

比如compile这个阶段,对应的是mvn complie这个命令,但是实际上是maven-compiler-plugin这个插件在起作用

每个插件在执行的时候会有多个任务,每个任务被称作这个插件的一个目标(goal),这个目标都是可以对应上maven生命周期中某个阶段(phase)的,这里重新看下上述mvn install命令(其中有个插件就是叫做maven-install-plugin)的执行结果

D:\Work\moudle\maven\mavenapp1> mvn install
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building mavenapp1 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mavenapp1 ---
[INFO] Using ‘UTF-8‘ encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\Work\moudle\maven\mavenapp1\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ mavenapp1 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\Work\moudle\maven\mavenapp1\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mavenapp1 ---
[INFO] Using ‘UTF-8‘ encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\Work\moudle\maven\mavenapp1\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ mavenapp1 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\Work\moudle\maven\mavenapp1\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mavenapp1 ---
[INFO] Surefire report directory: D:\Work\moudle\maven\mavenapp1\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.company.maven01.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.007 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ mavenapp1 ---
[INFO] Building jar: D:\Work\moudle\maven\mavenapp1\target\mavenapp1-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ mavenapp1 ---
[INFO] Installing D:\Work\moudle\maven\mavenapp1\target\mavenapp1-1.0-SNAPSHOT.jar to D:\Users\haitao\.m
\company\maven01\mavenapp1\1.0-SNAPSHOT\mavenapp1-1.0-SNAPSHOT.jar
[INFO] Installing D:\Work\moudle\maven\mavenapp1\pom.xml to D:\Users\haitao\.m2\repository\com\company\m
\1.0-SNAPSHOT\mavenapp1-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10.977 s
[INFO] Finished at: 2015-08-05T12:27:50+08:00
[INFO] Final Memory: 21M/198M
[INFO] ------------------------------------------------------------------------

通过红色的部分可以看到mvn install这个命令是由很多个插件依次按照一定的顺序执行的结果,同时可以发现,红色的部分都是按照一定的格式:

{插件名}:{版本}:{任务}

可以看到 maven-resources-plugin这个插件在这里实际上执行了两种任务,即resources 和testResources

而这里的resource和testResources都对应了maven的default生命周期中两个phase。

更多的关于插件的信息,可以查看maven的官方网站,包括每个插件都可以执行什么样的任务都有详细的介绍。

显然的,默认情况下maven的每个阶段(phase)都已经绑定了一个默认的插件的任务目标,比如:

左边栏是生命周期的phase,右边是所对应的默认的插件的任务目标(goal),但实际上phase和goal并不是一对一的关系,而是一对多的关系,比如package这个阶段,项目可能并不想打包成jar格式而是别的格式,那么这里的package对应的goal就要变了,这里都是可以通过pom.xml描述文件来修改和定制

自定义插件绑定到maven生命周期



那么如果你想自己开发个插件,并且想让maven默认生命周期的某个阶段使用你自己的写的插件的某个任务目标,改如何做呢?

这一过程是通过将插件的目标(goal)绑定到生命周期的具体阶段(phase)来完成的。如:将maven-compiler-plugin插件的compile目标绑定到default生命周期的compile阶段,完成项目的源代码编译:

通过在pom.xml的build元素即可完成自定义插件(或者别的已有插件)对生命周期某个阶段的绑定,用户可以根据需要将任何插件目标绑定到任何生命周期的阶段,如:将maven-source-plugin的jar-no-fork目标绑定到default生命周期的package阶段,这样,以后在执行mvn package命令打包项目时,在package阶段之后会执行源代码打包,生成如:ehcache-core-2.5.0-sources.jar形式的源码包。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>2.2.1</version>
            <executions>
                <execution>
                    <id>attach-source</id>
                    <phase>package</phase><!-- 要绑定到的生命周期的阶段 -->
                    <goals>
                        <goal>jar-no-fork</goal><!-- 要绑定的插件的目标 -->
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
    ……
</build>
时间: 2024-08-25 03:49:13

Maven(二)核心知识点的相关文章

Java核心知识点学习----多线程 倒计时记数器CountDownLatch和数据交换的Exchanger

本文将要介绍的内容都是Java5中的新特性,一个是倒计时记数器---CountDownLatch,另一个是用于线程间数据交换的Exchanger. 一.CountDownLatch 1.什么是CountDownLatch? 倒计时计数器,调用CountDownLatch对象的CountDown()方法就将计数器减一,当计数到达0时,则所有等待者或者全部等待者开始执行. 2.如何用? new CountDownLatch(1); 直接new,其构造函数必须传一个int类型的参数,参数的意思是: c

Maven的核心概念:maven仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的

一.Maven坐标 1.1.什么是坐标? 在平面几何中坐标(x,y)可以标识平面中唯一的一点. 1.2.Maven坐标主要组成 groupId:组织标识(包名) artifactId:项目名称 version:项目的当前版本 packaging:项目的打包方式,最为常见的jar和war两种 样例: 1.3.Maven为什么使用坐标? Maven世界拥有大量构建,我们需要找一个用来唯一标识一个构建的统一规范. 拥有了统一规范,就可以把查找工作交给机器. 二.依赖管理 2.1.依赖配置 依赖配置主要

javascript系列之核心知识点(一)

JavaScript. The core. 1.对象 2.原型链 3.构造函数 4.执行上下文堆栈 5.执行上下文 6.变量对象 7.活动对象 8.作用域链 9.闭包 10.this值 11.总结 这篇文章是"ECMA-262-3 in detail"系列的一个摘要和总结.每一部分包含了对应章节的连接引用,所以你可以仔细去阅读得到一个更深刻的理解.适合的读者:资深程序员,专家.我们从探讨对象的概念开始,这也是ECMAScript的奠基石. 对象 ECMAScript,一个高度抽象的面向

Maven学习(四)-- Maven的核心概念

摘自:http://www.cnblogs.com/xdp-gacl/p/4051819.html 一.Maven坐标 1.1.什么是坐标? 在平面几何中坐标(x,y)可以标识平面中唯一的一点. 1.2.Maven坐标主要组成 groupId:组织标识(包名) artifactId:项目名称 version:项目的当前版本 packaging:项目的打包方式,最为常见的jar和war两种 样例: 1.3.Maven为什么使用坐标? Maven世界拥有大量构建,我们需要找一个用来唯一标识一个构建的

Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍

1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过start方法启动线程--->线程变为可运行可执行状态,然后通过数据产生共享,线程产生互斥---->线程状态变为阻塞状态---->阻塞状态想打开的话可以调用notify方法. 这里Java5中提供了封装好的类,可以直接调用然后构造阻塞状态,以保证数据的原子性. 2.如何实现? 主要是实现Blo

理解maven的核心概念

原文链接:http://www.cnblogs.com/holbrook/archive/2012/12/24/2830519.html 好久没进行java方面的开发了,最近又完成了一个java相关的任务,顺便重新体会了 maven 这一利器. 在使用过程中发现以前对maven的理解不够深入,借此机会重新梳理了一下maven的核心概念.相信理解了这些核心概念, 即使长时间不使用,以后再重新上手也会非常容易. 本文以类图的方式,介绍maven核心的12个概念以及相互之间的关系. Table of

Ubuntu 14.04 Android 使用Maven二 创建自己的Mavenproject

依据https://code.google.com/p/maven-android-plugin/wiki/GettingStarted 介绍,有两种方法能够创建Mavenproject. 第一种方法是用archetype, 可是我使用了之后,发现archetype产生的项目编译时有一个依赖找不到,无论了,先换其它方法. 另外一种方法就是使用android命令行创建项目,然后复制样例代码project的pom文件并改动, Ubuntu 14.04 设置Android开发环境 描写叙述了怎样用命令

Ubuntu 14.04 Android 使用Maven二 创建自己的Maven工程

根据https://code.google.com/p/maven-android-plugin/wiki/GettingStarted 介绍,有两种方法可以创建Maven工程. 第一种方法是用archetype, 但是我使用了之后,发现archetype产生的项目编译时有一个依赖找不到,不管了,先换其他方法. 第二种方法就是使用android命令行创建项目,然后复制例子代码工程的pom文件并修改, Ubuntu 14.04 设置Android开发环境 描述了如何用命令行创建项目 Ubuntu

Maven入门_四、Maven项目核心POM

四.Maven项目核心POM .xml pom定义了项目的基本信息,描述了项目的构建.依赖 1.Maven项目的基本坐标: <!-- 项目包名: 公司地址名称反写+项目名称--> <groupId>com.xusan</groupId> <!--项目模块名称:一般为 项目名-模块名 --> <artifactId>hello-word</artifactId> <!-- 指定当前pom 的版本--> <version

第五十二个知识点:选择一个先进的应用概念,如电子投票,拍卖或多方计算。这样一个系统的大致安全需求是什么

第五十二个知识点:选择一个先进的应用概念,如电子投票,拍卖或多方计算.这样一个系统的大致安全需求是什么 这是我们认为每个密码学博士一年级都应该知道的52件事中的最后一件.你可能已经收集了过去的52个博客,我们希望学生知道从理论到实践的各个方面.但关键是你需要在密码学中考虑的不仅是对遵守规则的玩家的安全,还有对不遵守规则的玩家的安全.让我们从投票.拍卖和多方计算的角度来研究这个问题. 让我们先讨论一下三个应用程序的含义. 在投票中,我们根绝投票者进行一些投票方案(得票最多者当选.多选.赞成投票或其