3. 本文中使用的工具
本文中的示例已使用以下工具进行了测试:
- NetBeans 6.8 至 7.1.2 版本。NetBeans 的安装方法详见 [ref3] 第 1.3.1 节。
- WampServer 2.2 版。WampServer 的安装方法详见 [ref3] 第 1.3.3 节;
- Maven 已集成到 NetBeans 中。接下来我们将介绍该工具。
3.1. Maven
3.1.1. 简介
Maven 的网址为 [http://maven.apache.org/index.html ]。据其创建者介绍:
Maven 的主要目标是让开发人员能够在最短时间内全面掌握开发项目的整体状态。为实现这一目标,Maven 重点关注以下几个关键领域:
- 简化构建流程
- 提供统一的构建系统
- 提供高质量的项目信息
- 提供开发最佳实践指南
- 支持向新功能的无缝迁移
Maven 已集成到 NetBeans 中,而我们将仅使用其其中一项功能:管理项目的库。这些库包含所有必须位于项目类路径中的 JAR 文件,其数量可能非常庞大。 例如,我们未来的项目将使用 Hibernate ORM(对象关系映射器)。该 ORM 包含数十个 JAR 文件。Maven 的优势在于,它使我们无需逐一了解这些文件。 我们只需在项目中指定需要 Hibernate,并提供定位该 ORM 主 JAR 文件所需的所有信息。随后,Maven 还会自动下载 Hibernate 所需的所有库。这些被称为 Hibernate 的依赖项。Hibernate 所需的某个库本身可能又依赖于其他归档文件,这些文件也会被一并下载。所有这些库都会被放置在一个名为“本地 Maven 仓库”的文件夹中。
Maven 项目易于共享。若将项目从一台计算机转移到另一台,且新计算机的本地仓库中不存在该项目的依赖项,系统会自动下载这些依赖项。
Maven 既可以独立使用,也可以集成到 NetBeans 或 Eclipse 等集成开发环境(IDE)中。
![]() |
- 在 [1] 中,创建一个新项目,
- 在 [2] 中,选择 [Maven] 类别和 [Java 应用程序] 项目类型,
![]() |
- 在 [3] 中,指定新项目的父目录,
- 在 [4] 中,为项目命名,
- 在 [5] 中,生成项目。
让我们来查看该项目的组成部分,并解释每个组件的作用。
![]() |
- 在 [1] 中:项目的不同分支:
- [源代码包]:项目的 Java 类;
- [测试包]:项目的测试类;
- [依赖项]:项目所需的、由 Maven 管理的 .jar 归档文件;
- [测试依赖项]:项目测试所需的、由 Maven 管理的 .jar 文件;
- [Java 依赖项]:项目所需但未由 Maven 管理的 .jar 文件;
- [项目文件]:Maven 和 NetBeans 的配置文件,
![]() |
- 在 [3] 中,[源代码包] 分支,
该分支包含项目 Java 类的源代码。NetBeans 已生成一个默认类:
package istia.st.mvexemple;
/**
* Hello world!
*
*/
public class App {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
![]() |
- 在 [4] 中,[Test Packages] 分支,其中包含项目测试类的源代码,
- 在 [5] 中,运行测试所需的 JUnit 3.8 库,
NetBeans 生成了一个默认类:
package istia.st.mvexemple;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest extends TestCase {
/**
* Create the test case
*
* @param testName
* name of the test case
*/
public AppTest(String testName) {
super(testName);
}
/**
* @return the suite of tests being tested
*/
public static Test suite() {
return new TestSuite(AppTest.class);
}
/**
* Rigourous Test :-)
*/
public void testApp() {
assertTrue(true);
}
}
这是一个 JUnit 3.8 测试。我们稍后将使用 JUnit 4.x 测试。
![]() |
- 在[6]中,此处的[Dependencies]部分为空,
该部分列出了项目所需且由 Maven 管理的所有库。此处列出的所有库都会由 Maven 自动下载。这就是为什么 Maven 项目需要互联网连接。下载的库将存储在本地。如果另一个项目需要一个本地已存在的库,则不会再次下载。我们将看到,这个库列表以及它们所在的仓库,都是在 Maven 项目配置文件中定义的。
![]() |
- 在[7]中,项目所需但未由Maven管理的库,
![]() |
- 在 [7] 中,是 Maven 项目的 [pom.xml] 配置文件。POM 代表项目对象模型(Project Object Model)。我们需要直接编辑此文件。
生成的 [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>istia.st</groupId>
<artifactId>mv-exemple</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mv-exemple</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>
- 第 5–8 行定义了将由 Maven 项目生成的 Java 工件。这些信息来自创建项目时使用的向导:
![]() |
Maven 工件由四个属性定义:
- [groupId]:类似于包名的信息。例如,Spring 框架的库具有 groupId=org.springframework,而 JSF 框架的库具有 groupId=javax.faces,
- [artifactId]:Maven 工件的名称。在 [org.springframework] 组中,我们可以找到以下 artifactId:spring-context、spring-core、spring-beans 等;而在 [javax.faces] 组中,则包含 artifactId jsf-api,
- [version]:Maven 工件的版本号。因此,工件 org.springframework.spring-core 具有以下版本:2.5.4、2.5.5、2.5.6、2.5.6.SECO1 等
- [packaging]:工件的格式,最常见的是 war 或 jar。
我们的 Maven 项目将在 [istia.st] 组(第 5 行)中生成一个 [jar](第 8 行),命名为 [mv-example](第 6 行),版本号为 [1.0-SNAPSHOT](第 7 行)。这四项信息必须能够唯一标识一个 Maven 工件。
第 17–24 行列出了 Maven 项目的依赖项,即项目所需的库列表。每个库都由四项信息(groupId、artifactId、version、packaging)定义。当缺少打包信息时(如本例),将默认使用 jar 打包格式。 还添加了一项信息:scope,它指定在项目生命周期的哪些阶段需要该库。默认值为 compile,表示该库在编译和执行时需要。值 test 表示该项目测试期间需要该库。此处的 JUnit 3.8.1 库即属于这种情况。如果该库不在机器上的本地仓库中,则会进行下载。
3.1.2. 运行项目
我们运行该项目:
![]() |
在[1]中,Maven项目被构建并执行[1]。NetBeans控制台中的日志如下:
结果见第23行。我们可以看到,即使在这个简单的情况下,Maven也下载了一些依赖项(第17行和第20行)。
3.1.3. Maven 项目的文件系统
![]() |
- [1]:项目的文件系统位于 [Files] 选项卡中,
- [2]: Java 源代码位于 [src/main/java] 文件夹中,
- [3]: Java 测试源代码位于 [src/test/java] 文件夹中,
- [4]: [target] 文件夹由项目构建生成,
- [5]: 这里,项目构建生成了一个归档文件 [mv-example-1.0-SNAPSHOT.jar]。
3.1.4. 本地 Maven 仓库
我们提到过,Maven 会下载项目所需的依赖项并将其存储在本地。您可以浏览此本地仓库:
![]() |
- 在 [1] 中,选择 [窗口 / 其他 / Maven 仓库浏览器] 选项,
- 在 [2] 处,将打开一个 [Maven 仓库] 选项卡,
- 在 [3] 中,它包含两个分支,一个用于本地仓库,另一个用于中央仓库。后者规模庞大。要查看其内容,必须更新其索引 [4]。此更新过程需要数十分钟。
![]() |
- 在 [5] 中,本地仓库中的库,
- 在 [6] 中,你会发现一个名为 [istia.st] 的分支,它对应于我们项目的 [groupId],
- 在 [7] 中,您可以访问本地仓库的属性,
- 在 [8] 中,您可以看到本地仓库的路径。了解这一点很有用,因为有时(虽然很少见)Maven 不再使用项目的最新版本。您进行修改后发现更改未被应用。此时,您可以手动删除本地仓库中与您的 [groupId] 对应的分支。这将迫使 Maven 从项目的最新版本重新创建该分支。
3.1.5. 使用 Maven 搜索工件
现在让我们学习如何使用 Maven 搜索工件。首先来看 [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>istia.st</groupId>
<artifactId>mv-exemple</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mv-exemple</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>
第 17–23 行定义了依赖项,我们将对其进行修改以使用库的最新版本。
![]() |
首先,我们移除当前的依赖项 [1]。随后修改 [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>istia.st</groupId>
<artifactId>mv-exemple</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mv-exemple</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies></dependencies>
</project>
第 17 行:已移除的依赖项不再出现在 [pom.xml] 中。现在,让我们在 Maven 仓库中搜索它。
![]() |
- 在 [1] 中,我们向项目添加了一个依赖项;
- 在 [2] 中,我们必须指定要查找的工件信息(groupId、artifactId、version、packaging(Type)和 scope)。首先指定 [groupId] [3],
- 在 [4] 处,我们按 [空格键] 显示可能的工件列表。这里显示 [junit] 和 [jnit-dep]。我们选择 [junit],
- 在 [5] 处,按照相同步骤,我们选择最新版本。打包类型为 jar,
- 在 [6] 处,我们选择 test 作用域,以表明该依赖项仅用于测试。
![]() |
在 [6] 处,添加的依赖项已出现在项目中。[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>istia.st</groupId>
<artifactId>mv-exemple</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mv-exemple</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>4.10</version>
<scope>test</scope>
<type>jar</type>
</dependency>
</dependencies>
</project>
请注意,[pom.xml] 文件中并未提及 [6] 中显示的 [hamcrest-core-1.1] 依赖项。这是因为它是 JUnit 4.10 的依赖项,而非项目本身的依赖项。这一点通过 [Dependencies] 分支中不同的图标得以体现。该依赖项已被自动下载。
现在假设我们不知道所需工件的 [groupId]。例如,我们想使用 Hibernate 作为 ORM(对象关系映射器),而我们仅知晓这一点。此时我们可以访问网站 [http://mvnrepository.com/]:
![]() |
在[1]处,您可以输入关键词。输入hibernate并执行搜索。
![]() |
- 在 [2] 中,选择 [groupId] org.hibernate 和 [artifactId] hibernate-core,
- 在 [3] 中,选择版本 4.1.2-Final,
- 在 [4] 中,我们将获取到需要粘贴到 [pom.xml] 文件中的 Maven 代码。让我们开始操作吧。
<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>istia.st</groupId>
<artifactId>mv-exemple</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mv-exemple</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>4.10</version>
<scope>test</scope>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.1.2.Final</version>
</dependency>
</dependencies>
</project>
我们保存 [pom.xml] 文件。随后 Maven 会下载新的依赖项。项目演变如下:
![]() |
- 在 [5] 中,[hibernate-core-4.1.2-Final] 依赖项。在其所在的仓库中,该 [artifactId] 同样由一个 [pom.xml] 文件描述。Maven 读取了该文件,并发现该 [artifactId] 存在依赖项。它也会下载这些依赖项。对于每个下载的 [artifactId],Maven 都会执行此操作。 最终,我们在 [6] 中发现了未直接请求的依赖项。这些依赖项通过与主 [artifactId] 不同的图标进行标识。
在本文中,我们主要利用 Maven 的这一特性。这使我们无需了解所用库的所有依赖项,而是让 Maven 来管理它们。此外,通过在开发者之间共享 [pom.xml] 文件,我们可以确保每位开发者确实使用的是相同的库。
在接下来的示例中,我们将仅提供所使用的 [pom.xml] 文件。读者只需使用该文件即可复现文档中描述的条件。此外,主流 Java IDE(Eclipse、NetBeans、IntelliJ、JDeveloper)均支持 Maven 项目。因此,读者可以使用自己喜欢的 IDE 来测试这些示例。


















