maven(四)maven使用入门

1、编写pom

Maven 项目的核心是 pom.xml。POM(Project Object Model,项目对象模型) 定义了项目的基本信息, 用于描述项目如何构建, 声明项目依赖, 等等。 现在我们先为 Hello World项目编写一个最简单的 pom.xml。
首先创建一个名为 mavenTests 的文件夹 , 打开该文件夹,新建一个名为 pom.xml 的文件

maven(四)maven使用入门_第1张图片

根元素下的第一个子元素 modelVersion 指定了当前 POM 模型的版本,对于 Maven2 及 Maven 3 来说,它只能是 4.0.0。
这段代码中最重要的是 groupId, artifactId 和 version 三行。 这三个元素定义了一个项目基本的坐标, 在 Maven的世界,任何的 jar、pom 或者 war 都是以基于这些基本的坐标进行区分的。groupId 定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联,譬如你在 googlecode 上建立了一个名为 myapp 的项目,那么 groupId 就应该是 com.googlecode.myapp,如果你的公司是 mycom,有一个项目为 myapp,那么 groupId 就应该是 com.mycom.myapp。

artifactId 定义了当前 Maven 项目在组中唯一的 ID, 我们为这个 Hello World 项目定义 artifactId 为 maven。为不同的子项目(模块)分配 artifactId,如:maven-util、maven-domain、maven-web 等等。顾名思义,version 指定了 mavenTests 项目当前的版本——0.0.1-SNAPSHOT。SNAPSHOT 意为快照,说明该项目还处于开发中,是不稳定的版本。随着项目的发展,version 会不断更新,如升级为 1.0、1.1-SNAPSHOT、1.1、2.0 等等。最后有一个name元素声明了一个对于用户更为友好的项目名称, 这不是必须的。

没有任何实际的 Java 代码,我们就能够定义一个 Maven 项目的 POM,这体现了 Maven 的一大优点,它能让项目对象模型最大程度地与实际代码相独立,我们可以称之为解耦,或者正交性,这在很大程度上避免了 Java代码和 POM 代码的相互影响。比如当项目需要升级版本时,只需要修改 POM,而不需要更改 Java 代码;而在POM 稳定之后,日常的 Java 代码开发工作基本不涉及 POM 的修改。

2.编写主代码

项目主代码和测试代码不同,项目的主代码会被打包到最终的构件中(比如 jar) ,而测试代码只在运行测试时用到,不会被打包。默认情况下,Maven 假设项目主代码位于 src/main/java 目录,我们遵循 Maven 的约定,创建该目录,然后在该目录下创建文件 com.alex.maven

maven(四)maven使用入门_第2张图片

这是一个简单的 Java 类,它有一个 sayHello()方法,一个String参数,返回一个 String。同时这个类还带有一个 main 方法,创建一个 HelloWorld 实例,调用 sayHello()方法,传一个Maven字符串,并将结果输出到控制台。关于该 Java 代码有两点需要注意。首先,在 95%以上的情况下,我们应该把项目主代码放到 src/main/java/目录下(遵循 Maven 的约定) ,而无须额外的配置,Maven 会自动搜寻该目录找到项目主代码。其次,该 Java 类的包名是 package com.alex.maven.Helloworld,这与我们之前在 POM 中定义的 groupId 和 artifactId 相吻合。一般来说,项目中 Java 类的包都应该基于项目的 groupId 和 artifactId,这样更加清晰,更加符合逻辑,也方便搜索构件或者 Java 类。代码编写完毕后,我们使用 Maven 进行编译,在项目根目录下运行命令 mvn clean compile ,我们会得到如下输出:

maven(四)maven使用入门_第3张图片

clean 告诉 Maven 清理输出目录 target/,compile 告诉 Maven 编译项目主代码,从输出中我们看到 Maven 首先执行了 clean:clean 任务,删除 target/目录,默认情况下 Maven 构建的所有输出都在 target/目录中;接着执行resources:resources 任务(未定义项目资源,暂且略过) ;最后执行 compiler:compile 任务,将项目主代码编译至target/classes 目录。

3、编写测试代码

为了使项目结构保持清晰,主代码与测试代码应该分别位于独立的目录中。3.2 节讲过 Maven 项目中默认的主代码目录是 src/main/java,对应地,Maven 项目中默认的测试代码目录是 src/test/java。因此,在编写测试用例之前,我们先创建该目录。

在 Java 世界中,由 Kent Beck 和 Erich Gamma 建立的 JUnit 是事实上的单元测试标准。要使用 JUnit,我们首先需要为 Hello World 项目添加一个 JUnit 依赖,修改项目的 POM 为 Hello World 的 POM 添加依赖

maven(四)maven使用入门_第4张图片

代码中添加了 dependencies 元素,该元素下可以包含多个 dependency 元素以声明项目的依赖,这里我们添加了一个依赖——groupId 是 junit,artifactId 是 junit,version 是 4.0。前面我们提到 groupId、 artifactId 和 version 是任何一个 Maven 项目最基本的坐标, JUnit 也不例外,有了这段声明,Maven 就能够自动下载 junit-4.0.jar。也许你会问,Maven 从哪里下载这个 jar呢?在 Maven 之前,我们可以去 JUnit 的官网下载分发包。而现在有了 Maven,它会自动访问中央仓库( http://repo1.maven.org/maven2/ ),下载需要的文件。读者也可以自己访问该仓库,打开路径junit/junit/4.0/,就能看到 junit-4.0pom 和 junit-4.0.jar
上述 POM 代码中还有一个值为 test 的元素 scope,scope 为依赖范围,若依赖范围为 test 则表示该依赖只对测试有效,换句话说,测试代码中的 import JUnit 代码是没有问题的,但是如果我们在主代码中用 import JUnit代码,就会造成编译错误。如果不声明依赖范围,那么默认值就是 compile,表示该依赖对主代码和测试代码都有效。
配置了测试依赖, 接着就可以编写测试类, 回顾一下前面的 HelloWorld 类, 现在我们要测试该类的 sayHello()方法,检查其返回值是否为“Hello Maven”。在 src/test/java 目录下创建文件,
Hello World 的测试代码

maven(四)maven使用入门_第5张图片

一个典型的单元测试包含三个步骤:一,准备测试类及数据;二,执行要测试的行为;三,检查结果。上述样例中,我们首先初始化了一个要测试的 HelloWorld 实例,接着执行该实例的 sayHello()方法并保存结果到 result变量中,最后使用 JUnit 框架的 Assert 类检查结果是否为我们期望的”Hello Maven”。在 JUnit 3 中,约定所有需要执行测试的方法都以 test 开头,这里我们使用了 JUnit 4,但我们仍然遵循这一约定,在 JUnit 4 中,需要执行的测试方法都应该以@Test 进行标注。

测试用例编写完毕之后就可以调用 Maven 执行测试,运行 mvn clean test :

maven(四)maven使用入门_第6张图片

我们看到 compiler:testCompile 任务执行成功了,测试代码通过编译之后在 target/test-classes 下生成了二进制文件,紧接着 surefire:test 任务运行测试,surefire 是 Maven 世界中负责执行测试的插件,这里它运行测试用例HelloWorldTest,并且输出测试报告,显示一共运行了多少测试,失败了多少,出错了多少,跳过了多少。显然,我们的测试通过了——BUILD SUCCESSFUL。

4、打包和运行

将项目进行编译、测试之后,下一个重要步骤就是打包(package) 。Hello World 的 POM 中没有指定打包类型,使用默认打包类型 jar,我们可以简单地执行命令 mvn clean package 进行打包,可以看到如下输出:

maven(四)maven使用入门_第7张图片

类似地,Maven 会在打包之前执行编译、测试等操作。这里我们看到 jar:jar 任务负责打包,实际上就是 jar插件的 jar 目标将项目主代码打包成一个名为maven-0.0.1-SNAPSHOT.jar 的文件,该文件也位于 target/输出目录中,它是根据 artifact-version.jar 规则进行命名的,如有需要,我们还可以使用 finalName 来自定义该文件的名称。
至此,我们得到了项目的输出,如果有需要的话,就可以复制这个 jar 文件到其他项目的 Classpath 中从而使用 HelloWorld 类。但是,如何才能让其他的 Maven 项目直接引用这个 jar 呢?我们还需要一个安装的步骤,执行mvn clean install:

maven(四)maven使用入门_第8张图片

在打包之后,我们又执行了安装任务 install:install,从输出我们看到该任务将项目输出的 jar 安装到了 Maven本地仓库中,我们可以打开相应的文件夹看到 maven 项目的 pom 和 jar。之前讲述 JUnit 的 POM 及 jar 的下载的时候, 我们说只有构件被下载到本地仓库后, 才能由所有 Maven 项目使用, 这里是同样的道理, 只有将 HelloWorld 的构件安装到本地仓库之后,其他 Maven 项目才能使用它。
我们已经将体验了 Maven 最主要的命令: mvn clean compile、 、 mvn clean test、 、 mvn clean package、 、 mvn cleaninstall。执行 test 之前是会先执行 compile 的,执行 package 之前是会先执行 test 的,而类似地,install 之前会执行 package。我们可以在任何一个 Maven 项目中执行这些命令,而且我们已经清楚它们是用来做什么的。
到目前为止,我们还没有运行 maven 项目,不要忘了 HelloWorld 类可是有一个 main 方法的。默认打包生成的 jar 是不能够直接运行的,因为带有 main 方法的类信息不会添加到 manifest 中(我们可以打开 jar 文件中的META-INF/MANIFEST.MF 文件,将无法看到 Main-Class 一行)。为了生成可执行的 jar 文件,我们需要借助maven-shade-plugin,配置该插件如下:

maven(四)maven使用入门_第9张图片

plugin 元素在 POM 中的相对位置应该在下面。我们配置了 mainClass 为com.alex.maven.HelloWorld,项目在打包时会将该信息放到 MANIFEST 中。现在执行 mvn clean
install , 待 构 建 完 成 之 后 打 开 target/ 目 录 , 我 们 可 以 看 到 maven-0.0.1-SNAPSHOT.jar 和
original-maven-0.0.1-SNAPSHOT.jar,前者是带有 Main-Class 信息的可运行 jar,后者是原始的 jar,

现在,我们在项目根目录中执行该 jar 文件:
E:\test-maven\mavenTests\target>java -jar maven-0.0.1-SNAPSHOT.jar

Hello Maven

控制台输出为 Hello Maven,这正是我们所期望的。
这里介绍了 maven 项目,侧重点是 Maven 而非 Java 代码本身,介绍了 POM、Maven 项目结构、以及如何编译、测试、打包,等等。

5、使用 Archetype 生成项目骨架

maven 项目中有一些 Maven 的约定:在项目的根目录中放置 pom.xml,在 src/main/java 目录中放置项目的主代码,在 src/test/java 中放置项目的测试代码。我之所以一步一步地展示这些步骤,是为了能让可能是 Maven初学者的你得到最实际的感受。我们称这些基本的目录结构和 pom.xml 文件内容称为项目的骨架,当你第一次创建项目骨架的时候,你还会饶有兴趣地去体会这些默认约定背后的思想,第二次,第三次,你也许还会满意自己的熟练程度,但第四、第五次做同样的事情,就会让程序员恼火了,为此 Maven 提供了 Archetype 以帮助我们快速勾勒出项目骨架。

我们使用 maven archetype 来创建该项目的骨架,离开当前的 Maven 项目目录。
如果是 Maven 3,简单的运行:mvn archetype:generate
如果是 Maven 2,最好运行如下命令:mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-5:generate

我们实际上是在运行插件 maven-archetype-plugin ,注意冒号的分隔 , 其格式为groupId:artifactId:version:goal , org.apache.maven.plugins 是 maven 官方插件的 groupId, maven-archetype-plugin 是archetype 插件的 artifactId,generate 是我们要使用的插件目标。

紧接着我们会看到一段长长的输出,有很多可用的 archetype 供我们选择,包括著名的 Appfuse 项目的
archetype,JPA 项目的 archetype 等等。每一个 archetype 前面都会对应有一个编号,同时命令行会提示一个默认的编号,其对应的 archetype 为 maven-archetype-quickstart,我们直接回车以选择该 archetype,紧接着 Maven 会提示我们输入要创建项目的 groupId、artifactId、 version、以及包名 package,如下输入并确认:

maven(四)maven使用入门_第10张图片

Archetype 插件将根据我们提供的信息创建项目骨架。在当前目录下,Archetype 插件会创建一个名为
helloworld(我们定义的 artifactId)的子目录,从中可以看到项目的基本结构:基本的 pom.xml 已经被创建,里面包含了必要的信息以及一个 junit 依赖;主代码目录 src/main/java 已经被创建,在该目录下还有一个 Java 类com.alex.maven.App, 注意这里使用到了我们刚才定义的包名, 而这个类也仅仅只有一个简单的输出 Hello World!的 main 方法;测试代码目录 src/test/java 也被创建好了,并且包含了一个测试用例com.alex.maven.AppTest。
Archetype 可以帮助我们迅速地构建起项目的骨架,在前面的例子中,我们完全可以在 Archetype 生成的骨架的基础上开发 Hello World 项目以节省我们大量时间。此外,我们这里仅仅是看到了一个最简单的 archetype,如果你有很多项目拥有类似的自定义项目结构以及配置文件,你完全可以一劳永逸地开发自己的 archetype,然后在这些项目中使用自定义的 archetype 来快速生成项目骨架。

你可能感兴趣的:(maven,maven,架构,入门经典)