[7.14实习笔记] Maven入门

今天主要学习了Maven。整理记录一下。

Maven 是 Java 项目的一个构建工具,阿里内部使用Maven 2.2.1作为项目构建工具。

【Tips】关于Maven和后面WebX的学习,建议参照WebX提供的样例petstore进行对照理解。petstore的Github仓库地址为:https://github.com/webx/citrus-sample/tree/master/petstore

安装配置

安装

安装过程在上一篇博客中已经写过了:

[7.11实习笔记] 环境搭建 JDK+IDEA+MAVEN+JBOSS+HSF+SVN

配置

首先,我们要介绍一下仓库的概念。

在不用Maven的时候,比如说以前我们用Ant构建项目,在项目目录下,往往会看到一个名为/lib的子目录,那里存放着各类第三方依赖jar文件,如log4j.jar,junit.jar等等。每建立一个项目,你都需要建立这样的一个/lib目录,然后复制一对jar文件,这是很明显的重复。重复永远是噩梦的起点,多个项目不共用相同的jar文件,不仅会造成磁盘资源的浪费,也使得版本的一致性管理变得困难。此外,如果你使用版本管理工具,如SVN,你需要将大量的jar文件提交到代码库里,可是版本管理工具在处理二进制文件方面并不出色。

Maven仓库就是放置所有JAR文件(WAR,ZIP,POM等等)的地方,所有Maven项目可以从同一个Maven仓库中获取自己所需要的依赖JAR,这节省了磁盘资源。此外,由于Maven仓库中所有的JAR都有其自己的坐标(坐标的概念将在下面提到),该坐标告诉Maven它的组ID,构件ID,版本,打包方式等等,因此Maven项目可以方便的进行依赖版本管理。你也不再需要提交JAR文件到SCM仓库中,你可以建立一个组织层次的Maven仓库,供所有成员使用。

简言之,Maven仓库能帮助我们管理构件(主要是JAR)。

Maven的仓库分为本地仓库远程仓库。运行Maven的时候,Maven所需要的任何构件都是直接从本地仓库获取的。如果本地仓库没有,它会首先尝试从远程仓库下载构件至本地仓库,然后再使用本地仓库的构件。

关于仓库的 详细介绍,可参见:http://juvenshun.iteye.com/blog/359256

为什么要谈到这个概念呢?因为它是Maven的配置文件settings.xml的很重要的一部分。这个配置文件一般存在在两个地方,分别是用户目录下的.m2目录里,以及maven安装目录的conf目录中。

打开这个配置文件,我们主要关注下面几项内容:

<localrepository>:这一项指定了本地仓库的存储目录。

<mirrors>:这一项指定了远程仓库的镜像地址。如果你的地理位置附近有一个速度更快的central镜像,或者你想覆盖central仓库配置,或者你想为所有POM使用唯一的一个远程仓库(这个远程仓库代理的所有必要的其它仓库),你可以使用这项配置。

<profiles>:profile可以让我们定义一系列的配置信息,然后指定其激活条件。这样我们就可以定义多个profile,然后每个profile对应不同的激活条件和配置信息,从而达到不同环境使用不同配置信息的效果。比如说,我们可以通过profile定义在jdk1.5以上使用一套配置信息,在jdk1.5以下使用另外一套配置信息;或者有时候我们可以通过操作系统的不同来使用不同的配置信息,比如windows下是一套信息,linux下又是另外一套信息,等等。关于profile的具体使用可参见:http://haohaoxuexi.iteye.com/blog/1900568

IntelliJ IDEA中配置Maven

在IntelliJ IDEA中使用Maven,可以在File→Settings→Project Settings→Maven中进行设置。

其中可以在Runner项下设置vm options: -Xmx512m -XX:MaxPermSize=1024m

项目结构

Maven的项目使用一个统一的约定的标准目录结构(Standard Directory Layout)。如下所示:

my-app
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

这是一个典型的项目目录结构。

目录结构最顶层,是一个POM文件pom.xml(关于POM会在下面详细讲)。另外也可以有README.txt,LICENSE.txt等说明性文本。

子目录只有两种,src和target。其中target主要是存储build出来的东西的,src是存储所有的源代码的。它可以有这几种子目录:main(存放主要的构建代码);test(存放单元测试代码和资源),site,等。

在存储源代码的目录下(main,test等),有java(存放java代码),webapp(存放网络应用程序代码)和resource(存放资源)等目录。

src/main/java 应用程序/库的源代码
src/main/resources 应用程序/库的资源
src/main/filters 资源过滤文件
src/main/config 配置文件
src/main/scripts 应用程序/库的脚本
src/main/webapp 网络应用程序源代码
src/test/java 测试源代码
src/test/resources 测试资源
src/test/filters 测试资源过滤文件
src/it 集成测试(主要用于插件)
src/assembly 装配说明
src/site 站点
LICENSE.txt 项目许可协议
NOTICE.txt 项目所依赖的库所要求的说明和权限
README.txt 项目自述文件

POM

现在进入了Maven很重要的一个概念:POM(Project Object Model)。POM是Maven的核心,它以XML格式描述了所有与项目有关的信息。

首先介绍一个概念:坐标

坐标是指项目的唯一标识,以 GAV(groupId,artifactId 和 version)区分,这里我们可以将 groupId 理解为某某公司的 xxx 组或者产品线,开发了某一个项目,对应的版本为 XXX。这里 groupId 包含公司和内部组(或产品线)的信息,如 org.apache.commons,表示 Apache
软件组织下的 Java Commponents 产品线;ArtifactId 则表示项目的名称,如 commons-io,表示项目名称,Version 则表示某一 Artifact 的版本,如 1.3.2,1.3.3-SNAPSHOT 等。

当我们打开一个POM文件,首先看到的是一段描述我们正在建立的artifact信息:

[xml]
<?xml version="1.0" encoding="UTF-8"?>
<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>
[/xml]

这是强制性的开端部分。接下来是一组坐标。描述了当前项目的groupId, artifactId, version和name。

下面是<properties>。我们可以把properties理解为一组自定义的变量。我们可以在下面定义的依赖中使用这些变量,这样未来在我们需要升级包版本等场景时,可以通过修改变量的值来方便的实现。大家可以参照petstore的pom.xml文件来理解。

而后是依赖管理的部分。

[xml]
<dependencies>
<dependency>
<groupId>jdbm</groupId>
<artifactId>jdbm</artifactId>
<version>1.0</version>
</dependency>
[/xml]

这是一个获取jdbm的简单依赖。默认情况下,Maven通过访问http://www.ibibio.ort/maven2/来获得依赖,如果你查看jdbm/jdbm/1.0/目录,就会发现jdbm-1.0.jar文件,Maven将恢复它;以及一个简短的jdbm pom.xml文件,它列举artifact本身拥有的任何依赖。你可以手动浏览ibibio贮藏库或使用MVN Registry这样的网站来搜索贮藏库。

下一个要讨论的依赖是dwr,但你在ibibio贮藏库中找不到它。你必须将它安装到我们自己的本地贮藏库中。

[xml]
<dependency>
<groupId>dwr</groupId>
<artifactId>dwr</artifactId>
<version>2.0M3</version>
</dependency>
[/xml]

下一个依赖为Java Servlet API。在ibibio库中可以找到它,但我们只有在建立项目的时候才需要它;因为当我们配置一台网络服务器时,servlet API已经存在。

[xml]
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4-20040521</version>
<scope>provided</scope>
</dependency>
[/xml]

scope说明何时需要这个artifact,因此“provided”说明artifact由运行时间环境提供。另一个scope类型为“test”,它说明只有在测试时需要artifact。例如,我们这样包括Junit:

[xml]
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
[/xml]

那么,我们如果想引入一个依赖,应该怎么写这个dependency呢?其实我们可以通过远程仓库来搜索每个构建对应的XML描述。

常用的搜索页面有:maven.oschina.net,以及search.maven.org。我们在其中搜索一个构建,便可以得到它对应的XML描述。

现在,POM还剩最后一块内容:插件。

[xml]
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
[/xml]

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

生命周期

Maven强大的一个重要的原因是它有一个十分完善的生命周期模型(lifecycle),这个生命周期可以从两方面来理解,第一,顾名思义,运行Maven的每个步骤都由它来定义的,这种预定义的默认行为使得我们使用Maven变得简单,相比而言,Ant的每个步骤都要你手工去定义。第二,这个模型是一种标准,在不同的项目中,使用Maven的接口是一样的,这样就不用去仔细理解每个项目的构建了,一般情况下,mvn clean install 这样的命令是通用的。

Maven有三套相互独立的生命周期,请注意这里说的是“三套”,而且“相互独立”,初学者容易将Maven的生命周期看成一个整体,其实不然。这三套生命周期分别是:

  • Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
  • Default Lifecycle 构建的核心部分,编译,测试,打包,部署等等。
  • Site Lifecycle 生成项目报告,站点,发布站点。

我再次强调一下它们是相互独立的,你可以仅仅调用clean来清理工作目录,仅仅调用site来生成站点。当然你也可以直接运行 mvn clean install site 运行所有这三套生命周期。

知道了每套生命周期的大概用途和相互关系以后,来逐个详细看一下每套生命周期,Clean和Site相对比较简单,先解释一下。

每套生命周期都由一组阶段(Phase)组成,我们平时在命令行输入的命令总会对应于一个特定的阶段。比如,运行mvn clean ,这个的clean是Clean生命周期的一个阶段。有点绕?要知道有Clean生命周期,也有clean阶段。Clean生命周期一共包含了三个阶段:

  • pre-clean  执行一些需要在clean之前完成的工作
  • clean  移除所有上一次构建生成的文件
  • post-clean  执行一些需要在clean之后立刻完成的工作

mvn clean 中的clean就是上面的clean,在一个生命周期中,运行某个阶段的时候,它之前的所有阶段都会被运行,也就是说,mvn clean 等同于 mvn pre-clean clean ,如果我们运行 mvn post-clean ,那么 pre-clean,clean 都会被运行。这是Maven很重要的一个规则,可以大大简化命令行的输入。

下面看一下Site生命周期的各个阶段:

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

这里经常用到的是site阶段和site-deploy阶段,用以生成和发布Maven站点,这可是Maven相当强大的功能,Manager比较喜欢,文档及统计数据自动生成,很好看。

最后,来看一下Maven的最重要的Default生命周期,绝大部分工作都发生在这个生命周期中,这里只解释一些比较重要和常用的阶段:

  • validate
  • 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     将最终的包复制到远程的仓库,以让其它开发人员与项目共享。

基本上,根据名称我们就能猜出每个阶段的用途,关于其它阶段的解释,请参考 http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

记住,运行任何一个阶段的时候,它前面的所有阶段都会被运行,这也就是为什么我们运行mvn install 的时候,代码会被编译,测试,打包。

骨架

Maven约定的项目目录结构,如果手动创建,每个工程的重复工作非常多。为此,Maven提供了Archetype以帮助我们快速勾勒出项目骨架。

在IntelliJ IDEA中,使用Maven的骨架创建项目非常简单。我们只需选择File→New Project→Maven,勾选Create from archetype,然后在下方选择所需要使用的骨架(例如maven-archetype-webapp),点击Next按照向导提示操作即可。在选择骨架时,也可以直接输入关键词查找相应的骨架。

资料推荐

一些maven书籍介绍和一些maven视频介绍:
http://pan.baidu.com/s/1hq00qLA

国外非常不错的学习材料网站,集成了介绍、快速引导,书籍推荐等:
http://www.tutorialspoint.com/maven/index.htm

maven官网:
http://maven.apache.org/

官网介绍什么是maven:
http://maven.apache.org/what-is-maven.html

maven2和maven3的区别(目前主流是maven3):
http://tech.it168.com/a2010/1108/1123/000001123274_all.shtml
http://www.infoq.com/cn/news/2011/07/xxb-maven-10-time-to-update

maven下载:
http://maven.apache.org/download.cgi
windows需要下载的文件:apache-maven-版本号-bin.zip

maven官网5分钟速成:
http://maven.apache.org/guides/getting-started/maven-in-five-minutes.html

maven官网入门指南:
http://maven.apache.org/guides/getting-started/index.html

FAQ英文官网:
http://maven.apache.org/general.html

FAQ英文非官网:
http://docs.codehaus.org/display/MAVENUSER/FAQs-1

maven一些插件列表:
http://maven.apache.org/plugins

Maven 的41种骨架功能介绍:
http://www.cnblogs.com/iusmile/archive/2012/11/14/2770118.html
http://docs.codehaus.org/display/MAVENUSER/Archetypes+List

2 thoughts on “[7.14实习笔记] Maven入门

Leave a Reply

Your email address will not be published. Required fields are marked *