Maven初体验

——————————————[color=red]准备活动[/color]——————————————————
一: 关于为什么要使用Maven?

1、 Maven的库是由开源组织维护,不需要我们再花精力去管理第三方库,即使自己维护,也比较方便。

2、 Maven对jar包的版本管理有工具上的支持,比如将Release版本和Snapshot版本开,有利于SCM管理。

3、 Maven是标准,用过的人多,不需要额外培训

4、 Maven的plugin比较多,可以有更多的功能, Maven现有体系比较开饭,采用的技术相对比较通用和成熟,Maven的plugin机制也可以便于我们扩展更多功能。

5、 Maven的库下载是即用即下,不需要实现全部down下来,Maven的插件也是自动升级的,可以方便我们扩展新功能。

6、 可以很方便的与eclipse、IDEA这样的主流的IDE集成

7、 仓库管理器:它的出现有两个目的:首先它的角色是一个高度可配置的介于你的组织与公开的Maven仓库之间的代理,其次它为你的组织提供了一个可部署你组织内部生成的构建(第二方库)的地方。

8、 版本管理功能,这里的版本管理不是指第三方库的版本管理,而是项目的版本管理。

9、 站点功能: 它的出现让我们可以对项目的状态一目了然,,可以自动的把项目的各种状态和各种报表以站点的形式发布到内部网或者外部网,可以随时随地查看项目状态。


二: 理解 Maven 2 依赖项管理模型

依赖项开发适应于这样的项目,其软件组件(称作模块 )是由不同的项目团队开发的。它支持持续独立开发,也支持对所有依赖模块进行精炼。

这个团队协作场景在通过 Internet 建立和维护的开源项目中十分常见,由于内部开发大受开源或外包世界的冲击和影响,这种场景在合作开发的圈子里日益盛行。


解析项目依赖项


Maven 2 依赖项管理引擎帮助解析构建过程中的项目依赖项。实践中,依赖项在 pom.xml 文件内的 <dependencies> 元素中指定,并作为 POM 的一部分注入到 Maven 中。
项目依赖项存储在存储库服务器(在 Maven 术语中简单地称之为存储库 )上。要成功的解析依赖项,需要从包含该工件的存储库里找到所需的依赖性工件。

基于 POM 中的项目依赖项信息,该依赖项解析器试图以下列方式解析依赖项:

1. 检查本地存储库中的依赖项。
2. 检查远程存储库列表中的依赖项。
3. 如果前两步失败,则报告一个错误。

默认情况下,第二步中所涉及的第一个远程存储库是一个能在全球访问的集中式 Maven 2 存储库,它包含了最流行的开源项目的一些工件。在内部开发中,可以设置额外的远程存储库来包含从内部开发模块中发布的工件。可以使用 settings.xml 中的 <repositories> 元素来配置这些额外的远程存储库。
Maven 本地存储库和远程存储库

Maven 2 本地存储库是磁盘上的一个目录,通常位于 HomeDirectory/.m2/repository

。这个库扮演着高性能本地缓存的角色,存储着在依赖项解析过程中下载的工件。远程存储库要通过网络访问。可以在 settings.xml 配置文件中维护一个远程存储库列表以备使用。

通过 settings.xml 配置 Maven 可以在一个 settings.xml 文件中指定影响 Maven 操作的配置属性。默认的设置文件是 MavenInstallationDirectory/conf/settings.xml。Maven 2 用户可通过维护

UserHomeDirectory/.m2/settings.xml 来覆盖一些配置属性。参见 Maven 设置参考

,获取更多有关可配置设置的信息。 确保单个的工件 将 Maven 2 用于项目构建时,依赖项解析通过一个集中的存储库确保只存在一个依赖性工件,而不考虑有多少项目或子项目引用该工件。这是多模块项目构建中一个重要的属性,因为包含多个工件会导致一些项目一致性和集成方面的问题。
[b]
总结:[/b]
Maven的优点
[1]build逻辑可以被重用。在Ant中可能需要多次重复地写相同的语句,但由于POM的继承性,可以复用其它的POM文件中的语句。这样既可以写出清晰的build语句,又可以构造出层次关系良好的build工程。
[2]不必关注build工作的实现细节。我们只需要使用一些build生命周期短语就可以达到我们的目标,而不必管Maven是如何做到这些的。如,只需要告诉Maven要安装(install),那么它自然就会验证,编译,打包,及安装。
[3]Maven会自动加载工程依赖的artifact所依赖的其它artifact(Transitive Dependency),而不用显示的将这些artifact全部写到dependency中。
[4]如果完全使用Maven的标准目录布局,那么可以极大地减少配置细节。


—————————[color=red]Maven的安装与配置及demo[/color]——————————————

1、 下载
tp://maven.apache.org/download.html
2、 安装
JDK:jdk1.6
2.1 解压缩maven-2.0.11-bin.zip 到你想安装的位置,如D:/software/。

2.2 设置Maven系统环境变量,M2_HOME=D:/software/maven-2.0.11。

2.3 添加Maven bin目录至系统环境变量PATH中, %M2_HOME%\bin。

2.4 确认Maven的安装:

cmd > mvn -version

提示Maven version 2.0.11即安装成功。

3、
package com.demo.maven;

/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}



<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.demo.mvn</groupId>
<artifactId>webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>webapp 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>webapp</finalName>
</build>
</project>


<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.demo.maven</groupId>
<artifactId>app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

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

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>


mvn install:install-file -DgroupId=com.demo.mvn=1.0-SNAPSHOT -Dpackaging=jar -Dfile=/path/to/file


[color=darkred]Demo版(网友撰写、个人验证):[/color]

6.1 构想
由于只是阐述Maven的基本使用方法,所以本文将要设计的实例,只是一个简单的Maven demo。该实例包含两个工程:普通应用程序工程(app)和Web应用工程(webapp)。app工程提供一个简单的Java类;webapp工程只包含一个Servlet,并将使用app中的Java类。
该Demo的目标是能够正确地将webapp制成war包,以供部署时使用。要能够正确制作war,自然首先就必须要能够正确的编译源代码,且要将App模块制成jar包。本文创建的工程所在的目录是D:\maven\demo。
5.2 App工程
可以使用Maven的archetype插件来创建新工程,命令如下:
D:\maven\demo>mvn archetype:create -DgroupId=ce.demo.mvn -DartifactId=app
该工程的groupId是ce.demo.mvn,那么该工程的源文件将放在Java包ce.demo.mvn中。artifactId是app,那么该工程根目录的名称将为app。
当第一次执行该命令时,Maven会从central仓库中下载一些文件。这些文件包含插件archetype,以及它所依赖的其它包。该命令执行完毕后,在目录D:\maven\demo下会出现如下目录布局:

app
|-- pom.xml
`-- src
|-- main
| `-- java
| `-- ce
| `-- demo
| `-- mvn
| `-- App.java
`-- test
`-- java
`-- ce
`-- demo
`-- mvn
`-- AppTest.java因本文暂时不涉及JUnit测试,故请将目录app\src\test目录删除(不删除也没关系 ^_^)。然后再修改App.java文件,其完全内容如下:
... {
public String getStr(String str) {
return str;
}
}其实,如果我们能够清楚地知道Maven的标准目录布局,就可以不使用archetype插件来创建工程原型;如果我们要定制个性的目录布局,那么就更没有必要使用archetype插件了。

6.3 WebApp工程
我们仍然如创建app工程一样使用archetype插件来创建webapp工程,命令如下:
D:\maven\demo>mvn archetype:create -DgroupId=ce.demo.mvn -DartifactId=webapp -DarchetypeArtifactId=maven-archetype-webapp
第一次运行此命令时,也会从central仓库中下载一些与Web应用相关的artifact(如javax.servlet)。此命令与创建app的命令的不同之处是,多设置了一个属性archetypeArtifacttId,该属性的值为maven-archetype-webapp。即告诉Maven,将要创建的工程是一个Web应用工程。创建app工程时没有使用该属性值,是由于archetype默认创建的是应用程序工程。同样的,执行完该命令之后,会出现如下标准目录布局:

webapp
|-- pom.xml
`-- src
`-- main
`-- webapp
|-- index.jsp
|-- WEB-INF
`-- web.xml 根据5.1节的构想,webapp工程将只包含一个Servlet,所以我们不需要index.jsp文件,请将其删除。此时大家可以发现,目前的目录布局中并没有放Servlet,即Java源文件的地方。根据参考资源[6]中的附录B.1,以及app工程中Java源文件的布局,可以知道Servlet(它仍然是一个Java类文件)仍然是放在webapp\src\main\java目录中,请新建该目录。此处的Servlet是一个简单HelloServlet,其完整代码如下:

package hello;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import ce.demo.mvn.App; // 引用app工程中的App类

public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = -3696470690560528247L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
App app = new App();
String str = app.getStr("CE Maven Demo");
PrintWriter out = response.getWriter();
out.print("<html><body>");
out.print("<h1>" + str);
out.print("</body></html>");
}

6.4 POM文件
大家可以发现,在前面新建工程时,我们并没有提到各个工程中的pom.xml文件。现在将要讨论这个问题。我们先看看app工程中的POM文件,其完整内容如下:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>ce.demo.mvn</groupId>
<artifactId>app</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<name>CE Maven Demo -- App</name>
</project> 大家可以发现此我帖出来的内容与实际由archetype插件生成的POM文件的内容有些不同,但基本上是一致的。只是为了使文件中的语句更清晰,此处删除了一些冗余的内容,并修改了该工程的version和name的值,以与此例子的背景来符合。在目前情况下modelVersion值将被固定为4.0.0,这也是Maven2唯一能够识别的model版本。groupId,artifactId的值与创建工程时使用的命令中的相关属性值是一致的。packaging的值由工程的类型决定,如应用程序工程的packaging值为jar,Web应用工程的packaging值为war。上述情况也可以从webapp的POM文件中看出,下面将看看这个pom的完整内容。

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>ce.demo.mvn</groupId>
<artifactId>webapp</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>CE Maven Demo -- WebApp</name>

<dependencies>
<dependency>
<groupId>ce.demo.mvn</groupId>
<artifactId>app</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

比较app与webapp中的POM,除前面已经提过的packaging的差别外,我们还可以发现webapp中的POM多了dependencies项。由于webapp需要用到app工程中的类(见HelloServlet源代码),它还需要javax.servlet包(因为该包并不默认存在于jsdk中)。故,我们必须要将它们声明到依赖关系中。


6.5 执行
上述两个工程创建完毕后,就需要执行一些命令来看看会有什么结果出现。我们首先进入app目录,并执行命令mvn compile,然后会在该目录下发现新生成的目录target\classes,即编译后的class文件(包括它的包目录)就放在了这里。再执行命令mvn package,在目录target中就会生成app-1.0.jar文件。该文件的全名由如下形式确定:artifactId-version.packaging。根据第2章的叙述可以知道,执行命令mvn package时,将首先将产生执行命令mvn compile之后的结果,故如果要打包,那么只需要执行mvn package即可。
在app工程中执行完之后,就需要进入webapp工程了。进入webapp目录,此次将只执行mvn package命令(隐示地执行了compile过程)。此次命令的执行并不成功,会出现如下问题:

D:\maven\demo\webapp>mvn package
……
Downloading: http://repo1.maven.org/maven2/ce/demo/mvn/app/1.0/app-1.0.pom
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Error building POM (may not be this project's POM).
Project ID: ce.demo.mvn:app
Reason: Error getting POM for 'ce.demo.mvn:app' from the repository: Error transferring file
ce.demo.mvn:app:pom:1.0
from the specified remote repositories:
central (http://repo1.maven.org/maven2)
…… 由粗体内容可知,Maven正试图从central仓库下载app工程的artifact,但central仓库肯定不会有这个artifact,其结果只能是执行失败!由第1章artifact名词的解释可知,被依赖的artifact必须存在于仓库(远程或本地)中,但目前webapp所依赖的app必不存在于仓库中,所以执行只能失败。
解决这个问题有两种方法:[1]将app-1.0.jar安装到仓库中,使它成为一个artifact;[2]构建一个更高层次的工程,使app和webapp成为这个工程的子工程,然后从这个更高层次工程中执行命令。
第一种方法比较简单(见http://www.blogjava.net/jiangshachina/admin/EditPosts.aspx中的第一个主题),此处将详细讨论第2种方法(见5.6节)。


6.6 更高层次工程
我们可以将app和webapp的上一级目录demo作为这两个工程的 一个 更高层次工程,即使用app和webapp成为这个工程的子工程。为了使demo目录成为一个demo工程,只需要在这个目录下添加一个pom.xml文件,该文件内容如下:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>ce.demo</groupId>
<artifactId>mvn-demo</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<name>CE Maven Demo</name>

<modules>
<module>app</module>
<module>webapp</module>
</modules>
</project>
与app和webapp中的POM相比,demo的POM使用了modules项,modules用于声明本工程的子工程,module中的值对应于子工程的artifact名。而且该POM的packaging类型必须为pom。
有了demo工程后,我们只需要在demo目录下执行相关命令就可以了。通过如下命令即可验证:
[1]mvn clean – 消除工程(包括所有子工程)中产生的所有输出。这本文的实例中,实际上是删除target目录。由于之前的操作只有app工程产生了target目录,而webapp并没有,所以将只会删除app工程中的target目录。
[2]mvn package – 将工程制作成相应的包,app工程是作成jar包(app-1.0.jar),webapp工程是作成war包(webapp-1.0.war)。打开webapp-1.0.war包,可以发现app-1.0.jar被放到了WEB-INF的lib目录中。
6 小结
通过以上的叙述与实例,应该可以对Maven有一个粗略的认识了。使用Maven关键是要弄清楚如何写pom.xml文件,就如同使用Ant要会写build.xml文件一样。在POM中可以直接写入Ant的task脚本,也可以调用Ant的build.xml文件(推荐),所以Maven也可以完成Ant的绝大多数工作(但不必安装Ant)。注意:使用Maven就不要再过多的使用Ant脚本。
利用好Maven的继承特性及子工程的关系,可以很好地简化POM文件,并能够构建层次结构良好的工程,有利于工程的维护。


[color=red][b]试验小插曲:[/b][/color]
mvn install:install-file -Dfile=D:\maven\demo\app\target\app-1.0-SNAPSHOT.jar -DgroupId=com.demo.mvn -Dversion=1.0-SNAPSHOT -Dpackaging=jar -DgeneratePom=true
//TMD此行出错竟然是因为缺少-DartifactId=app 真是眼睛瞎掉了!!!

当然还有一个潜在的原因就是我的记事本被我设置 “自动换行”这样子导致每次将记事本中的信息粘贴到命令行下时就出错, 因为其会在换行处便开始执行;

查阅官方文档说可能的原因有:配置dependency时出错、
需要的.jar包不存在,访问权限

最起初我设置认为只需要将相应的.jar包放到reposity下就可以了呢
^_^ ^_^

+++++++++++++++++++关于使用的难点+++++++++++++++++++
使用Maven的一大难题,就是dependency和repository的管理,而由于官网的不堪忍受性,我们不得不使用local repository或者自建私服,在这种情况下,我们该怎么样处理第三方的依赖包呢?

1. 如果是本地的repository, 可以通过如下的脚本来安装:

mvn install:install-file -Dfile=path-to-your-artifact-jar -DgroupId=your.groupId -DartifactId=your-artifactId -Dversion=your-version -Dpackaging=jar -DgeneratePom=true

2.如果是自建的私服,并且是第三方jar的话,就要通过webdav插件来上传,Maven2.0.5宣称它已经support natively webdav protocol to upload artefacts,并且声称通过如下的命令行脚本就可以完成deploy的工作:(参见http://docs.codehaus.org/display/MAVENUSER/Upload+artifacts)mvn deploy:deploy-file -DrepositoryId=<your_repo_id>your-repository-id -Durl=dav:your-repository-url <your_repo_url> -DgroupId=</your_repo_url></your_repo_id>your.groupId<your_repo_id><your_repo_url><group_id> -DartifactId=<artifact_id></artifact_id></group_id></your_repo_url></your_repo_id>your-artifactId<your_repo_id><your_repo_url><group_id><artifact_id> -Dversion=<version>your-version -Dpackaging=<packaging>jar -Dfile=jar-name<file_path>可以我们两个人花了半天的时间,才发现这些声明纯属扯淡!存在的问题如下:1) 当前的Maven版本根本就没有对Webdav提供native的支持,2) 我们仍然需要手工创建一个pom.xml,把它和jar包放在同一个目录下,3</file_path></packaging></version></artifact_id></group_id></your_repo_url></your_repo_id>)<your_repo_id><your_repo_url><group_id><artifact_id><version><packaging><file_path> 在pom.xml里面,我们还要指定webdav的扩展,同时,pom文件中还需要指定artifactId, groupId和version,4</file_path></packaging></version></artifact_id></group_id></your_repo_url></your_repo_id>)<your_repo_id><your_repo_url><group_id><artifact_id><version><packaging><file_path> pom文件的名字必须是pom.xml!错了就无法找到该文件!下面是一个完整的pom.xml和命令行脚本:</file_path></packaging></version></artifact_id></group_id></your_repo_url></your_repo_id>

详细的内容参见网址:
http://www.iteye.com/topic/58265


————————————————[color=red]Maven的关键名词解释[/color]————————————
[b]Project[/b]:任何您想build的事物,Maven都可以认为它们是工程。这些工程被定义为工程对象模型(POM,Poject Object Model)。一个工程可以依赖其它的工程;一个工程也可以由多个子工程构成。

[b]POM[/b]:POM(pom.xml)是Maven的核心文件,它是指示Maven如何工作的元数据文件,类似于Ant中的build.xml文件。POM文件位于每个工程的根目录中。

[b]GroupId[/b]:groupId是一个工程的在全局中唯一的标识符,一般地,它就是工程名。groupId有利于使用一个完全的包名,将一个工程从其它有类似名称的工程里区别出来
[b]
Artifact[/b]:artifact是工程将要产生或需要使用的文件,它可以是jar文件,源文件,二进制文件,war文件,甚至是pom文件。每个artifact都由groupId和artifactId组合的标识符唯一识别。需要被使用(依赖)的artifact都要放在仓库(见Repository)中,否则Maven无法找到(识别)它们。

[b]Dependency[/b]:为了能够build或运行,一个典型的Java工程会依赖其它的包。在Maven中,这些被依赖的包就被称为dependency。dependency一般是其它工程的artifact。


[b]Plug-in[/b]:Maven是由插件组织的,它的每一个功能都是由插件提供的。插件提供goal(类似于Ant中的target),并根据在POM中找到的元数据去完成工作。主要的Maven插件要是由Java写成的,但它也支持用Beanshell或Ant脚本写成的插件。
[b]
Repository[/b]:仓库用于存放artifact,它可以是本地仓库,也可以是远程仓库。Maven有一个默认的远程仓库--central,可以从http://www.ibiblio.org/maven2/下载其中的artifact。在Windows平台上,本地仓库的默认地址是User_Home\.m2\repository

[b]Snapshot[/b]:工程中可以(也应该)有一个特殊版本,它的版本号包括SNAPSHOT字样。该版本可以告诉Maven,该工程正处于开发阶段,会经常更新(但还未发布)。当其它工程使用此类型版本的artifact时,Maven会在仓库中寻找该artifact的最新版本,并自动下载、使用该最新版。


————————[color=red]Maven核心配置文件pom.xml解析[/color]————————————
·project 这是所有pom.xml的顶层
·modelVersion 这个元素指出POM现在使用的对象模型版本,除非开发者强制性的为了
确保稳定性而进行的必要改变、一般都是不发生变化的。
·groupId 这个就是指出被被创建项目的唯一标识、通常使用域名。
·artifactId 这个元素指出了生成项目时的唯一主要的的名字、通常这个名字被作为
Jar的名字。
·packaging 打包类型 (e.g. JAR, WAR, EAR, etc.). 这个不仅仅意味着打包的产品类型
也指出了一个建造过程中的详细生命周期。
·version 这个元素指出在项目被生成的时候的版本,通常你所看到的
SNAPSHOT指的是开发进行的状态
·name 这个元素指出项目相识的名字、通常被用在Maven生成的文档中
·url 这个元素指出在哪里可以找到这个项目的站点、通常也被用到Maven的
文档中。
·description 这个元素为你的项目提供一个基本的描述,通常被用在Maven生成的文
档中。


——————————Ma[color=red]ven常用命令[/color]————————————————————
可以在命令行下键入:mvn -e 会弹出如下一些命令并查看相应的解释

mvn clean
mvn test
mvn install
mvn deploy
mvn site
mvn eclipse:eclipse


——————————————[color=red]待学:Maven+Eclipse[/color]————————————————————————
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值