1 概览
Maven是什么
Maven是一个项目管理和理解工具,为开发人员提供了完整的构建生命周期框架。 Maven使用标准的目录布局和默认的构建生命周期,开发团队几乎可以随时自动执行项目的构建基础架构。
如果有多个开发团队环境,Maven可以在很短的时间内按照标准设置工作方式。 由于大多数项目设置简单且可重用,Maven在创建报告,检查,构建和测试自动化设置时,使开发人员的生活变得轻松。
Maven为开发人员提供了管理以下方面的方法 -
Builds
Documentation
Reporting
Dependencies
SCMs
Releases
Distribution
Mailing list
总而言之,Maven简化并标准化了项目构建过程。 它无缝地处理编译,分发,文档,团队协作和其他任务。 Maven增加了可重用性,并负责大部分构建相关任务。
Maven的发展
Maven最初的设计是为了简化Jakarta Turbine项目的建设流程。 有几个项目,每个项目包含略有不同的ANT构建文件。 JAR被检入CVS。
然后Apache团队开发了Maven,它可以一起构建多个项目,发布项目信息,部署项目,跨多个项目共享JAR并帮助团队协作。
目的
Maven的主要目标是为开发人员提供以下内容 -
项目综合模型,可重复使用,可维护且易于理解。
与此声明模型交互的插件或工具。
Maven项目的结构和内容是在一个xml文件pom.xml中声明的,该文件被称为项目对象模型(POM),它是整个Maven系统的基本单元。 在后面的章节中,我们将详细解释POM。
惯例优于配置
Maven使用Convention over Configuration,这意味着开发人员不需要自己创建构建过程。
开发人员不必提及每个配置细节。 Maven为项目提供了合理的默认行为。 Maven项目创建时,Maven创建默认项目结构。 开发人员只需要相应地放置文件,不需要在pom.xml中定义任何配置。
作为示例,下表显示了项目源代码文件,资源文件和其他配置的默认值。 假设$ {basedir}表示项目位置 -
Item | Default |
source code | ${basedir}/src/main/java |
Resources | ${basedir}/src/main/resources |
Tests | ${basedir}/src/test |
Complied byte code | ${basedir}/target |
distributable JAR | ${basedir}/target/classes |
为了构建项目,Maven为开发人员提供了提供生命周期目标和项目依赖项(依赖于Maven插件功能及其默认约定)的选项。 大部分项目管理和构建相关任务都由Maven插件维护。
开发人员可以构建任何给定的Maven项目,而无需了解各个插件的工作方式。 我们将在后面的章节中详细讨论Maven插件。
Maven的特点
简单的项目设置遵循最佳实践。
在所有项目中使用一致。
依赖管理包括自动更新。
一个庞大且不断增长的图书馆库。
可扩展,可以轻松编写Java或脚本语言的插件。
无需额外配置即可轻松访问新功能。
基于模型的构建 - Maven能够将任意数量的项目构建到预定义的输出类型中,例如jar,war和metadata。
项目信息的一致网站 - 根据构建过程使用相同的元数据,maven能够生成一个网站和一个包含完整文档的PDF。
发布管理和发布发布 - 无需额外配置,maven将与您的源代码管理系统(如CVS)集成并管理项目发布。
向后兼容性 - 您可以轻松地将项目的多个模块从旧版Maven移植到Maven 3中。它也可以支持旧版本。
自动父级版本控制 - 无需在子模块中指定父级以进行维护。
并行构建 - 它分析项目依赖关系图并使您能够并行构建调度模块。使用此功能,您可以实现20-50%的性能提升。
更好的错误和完整性报告 - Maven改进了错误报告,它为您提供了一个指向Maven wiki页面的链接,您将在其中获得错误的完整描述。
2 环境变量的设置
Maven是一个基于Java的工具,所以首要的要求是在你的机器上安装JDK。它要求JDK1.7或者更高。
第1步 - 验证您的机器上的Java安装
打开控制台并执行以下java命令。
OS | Task | Command |
Windows | Open Command Console | c:\> java -version |
Linux | Open Command Terminal | $ java -version |
Mac | Open Terminal | machine:~ joseph$ java -version |
如果您没有安装Java,请从https://www.oracle.com/technetwork/java/javase/downloads/index.html安装Java软件开发工具包(SDK)。 我们假定Java 1.7.0.60为本教程的安装版本。
第2步 - 设置JAVA环境
将JAVA_HOME环境变量设置为指向计算机上安装Java的基本目录位置。 例如 -
OS | Output |
Windows | Set the environment variable JAVA_HOME to C:\Program Files\Java\jdk1.7.0_60 |
Linux | export JAVA_HOME=/usr/local/java-current |
Mac | export JAVA_HOME=/Library/Java/Home |
将Java编译器位置附加到系统路径。
OS | Output |
Windows | Append the string “;C:\Program Files\Java\jdk1.7.0.60\bin” to the end of the system variable, Path. |
Linux | export PATH=$PATH:$JAVA_HOME/bin/ |
Mac | not required |
如上所述,使用java -version命令验证Java安装。
第3步 - 下载Maven档案
从https://maven.apache.org/download.cgi下载Maven 2.2.1。
OS | Archive name |
Windows | apache-maven-3.3.1-bin.zip |
Linux | apache-maven-3.3.1-bin.tar.gz |
Mac | apache-maven-3.3.1-bin.tar.gz |
第4步 - 提取Maven档案
将档案解压缩到您想要安装Maven 3.3.1的目录。 子目录apache-maven-3.3.1将从存档创建。
OS | Location (can be different based on your installation) |
Windows | C:\Program Files\Apache Software Foundation\apache-maven-3.3.1 |
Linux | /usr/local/apache-maven |
Mac | /usr/local/apache-maven |
第5步 - 设置Maven环境变量
将M2_HOME,M2,MAVEN_OPTS添加到环境变量。
OS | Output |
Windows | Set the environment variables using system properties. M2_HOME=C:\Program Files\Apache Software Foundation\apache-maven-3.3.1 M2=%M2_HOME%\bin MAVEN_OPTS=-Xms256m -Xmx512m |
Linux | Open command terminal and set environment variables. export M2_HOME=/usr/local/apache-maven/apache-maven-3.3.1 export M2=$M2_HOME/bin export MAVEN_OPTS=-Xms256m -Xmx512m |
Mac | Open command terminal and set environment variables. export M2_HOME=/usr/local/apache-maven/apache-maven-3.3.1 export M2=$M2_HOME/bin export MAVEN_OPTS=-Xms256m -Xmx512m |
第6步 - 将Maven bin目录位置添加到系统路径
现在将M2变量附加到系统路径。
OS | Output |
Windows | Append the string ;%M2% to the end of the system variable, Path. |
Linux | export PATH=$M2:$PATH |
Mac | export PATH=$M2:$PATH |
第7步 - 验证Maven安装
现在打开控制台并执行以下mvn命令。
OS | Task | Command |
Windows | Open Command Console | c:\> mvn --version |
Linux | Open Command Terminal | $ mvn --version |
Mac | Open Terminal | machine:~ joseph$ mvn --version |
3 POM
POM代表项目对象模型(Project Object Model)。 它是Maven的基本工作单位。 它是一个XML文件,作为pom.xml驻留在项目的基本目录中。
POM包含有关该项目的信息以及Maven用于构建项目的各种配置细节。
POM还包含目标和插件。 在执行任务或目标时,Maven将在当前目录中查找POM。 它读取POM,获取所需的配置信息,然后执行目标。 一些可以在POM中指定的配置如下 -
project dependencies
plugins
goals
build profiles
project version
developers
mailing list
在创建POM之前,我们应该首先确定项目组(groupId),其名称(artifactId)及其版本,因为这些属性有助于唯一标识存储库中的项目。
POM示例
<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.companyname.project-group</groupId> <artifactId>project</artifactId> <version>1.0</version> </project> |
应该指出,每个项目应该有一个POM文件。
所有POM文件都需要项目元素和三个必填字段:groupId,artifactId,version。
存储库中的项目表示法是groupId:artifactId:version。
POM的最低要求 -
Sr.No. | Node & Description |
1 | Project root 这是项目根标签。 您需要指定基本的模式设置,例如apache模式和w3.org规范。 |
2 | Model version Model 版本需要为 4.0.0. |
3 | groupId 这是project 的group的ID。 这在组织或项目中通常是独一无二的。 例如,一家银行集团com.company.bank拥有所有银行相关项目。 |
4 | artifactId 这是该项目的标识。 这通常是项目的名称。 例如,消费者银行业务。 与groupId一起,artifactId定义存储库中工件的位置。 |
5 | version 这是该项目的版本。 与groupId一起,它在工件的存储库中用于将各个版本彼此分开。 例如 - com.company.bank:consumer-banking:1.0 com.company.bank:consumer-banking:1.1. |
父POM
Super POM是Maven的默认POM。 所有的POM都从父代或默认继承(尽管显式定义或不)。 这个基本的POM被称为超级POM,并且包含默认继承的值。
Maven使用有效的POM(来自super pom的配置加上项目配置)执行相关目标。 它可以帮助开发人员在pom.xml中指定最低配置细节。 虽然配置可以轻松覆盖。
查看超级POM默认配置的简单方法是运行以下命令:mvn help:effective-pom
在计算机上的任何目录中创建一个pom.xml。使用上面提到的示例pom的内容。
在下面的例子中,我们在C:\ MVN \ project文件夹中创建了一个pom.xml文件。
现在打开命令控制台,转到包含pom.xml的文件夹并执行以下mvn命令。
C:\MVN\project>mvn help:effective-pom |
Maven将开始处理并显示有效的pom。
[INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'help'. [INFO] ------------------------------------------------------------------------ [INFO] Building Unnamed - com.companyname.project-group:project-name:jar:1.0 [INFO] task-segment: [help:effective-pom] (aggregator-style) [INFO] ------------------------------------------------------------------------ [INFO] [help:effective-pom {execution: default-cli}] [INFO] ..... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: < 1 second [INFO] Finished at: Thu Jul 05 11:41:51 IST 2012 [INFO] Final Memory: 6M/15M [INFO] ------------------------------------------------------------------------ |
在应用继承,插值和配置文件后,在控制台中显示有效的POM。
<?xml version="1.0" encoding="UTF-8"?> <!-- ============================================== --> <!-- --> <!-- Generated by Maven Help Plugin on 2015-04-09T11:41:51 --> <!-- See: http://maven.apache.org/plugins/maven-help-plugin/ --> <!-- --> <!-- ==============================================-->
<!-- ==============================================--> <!-- --> <!-- Effective POM for project --> <!-- 'com.companyname.project-group:project-name:jar:1.0' --> <!-- --> <!-- ============================================== -->
<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.companyname.project-group</groupId> <artifactId>project</artifactId> <version>1.0</version> <build> <sourceDirectory>C:\MVN\project\src\main\java</sourceDirectory> <scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>C:\MVN\project\src\test\java</testSourceDirectory> <outputDirectory>C:\MVN\project\target\classes</outputDirectory> <testOutputDirectory>C:\MVN\project\target\test-classes</testOutputDirectory> <resources> <resource> <mergeId>resource-0</mergeId> <directory>C:\MVN\project\src\main\resources</directory> </resource> </resources> <testResources> <testResource> <mergeId>resource-1</mergeId> <directory>C:\MVN\project\src\test\resources</directory> </testResource> </testResources> <directory>C:\MVN\project\target</directory> <finalName>project-1.0</finalName>
<pluginManagement> <plugins> <plugin> <artifactId>maven-antrun-plugin</artifactId> <version>1.3</version> </plugin> <plugin> <artifactId>maven-assembly-plugin< /artifactId> <version>2.2-beta-2</version> </plugin> <plugin> <artifactId>maven-clean-plugin< /artifactId> <version>2.2</version> </plugin>
<plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> </plugin> <plugin> <artifactId>maven-dependency-plugin</artifactId> <version>2.0</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.4</version> </plugin>
<plugin> <artifactId>maven-ear-plugin</artifactId> <version>2.3.1</version> </plugin> <plugin> <artifactId>maven-ejb-plugin</artifactId> <version>2.1</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.2</version> </plugin>
<plugin> <artifactId>maven-jar-plugin</artifactId> <version>2.2</version> </plugin> <plugin> <artifactId>maven-javadoc-plugin</artifactId> <version>2.5</version> </plugin> <plugin> <artifactId>maven-plugin-plugin</artifactId> <version>2.4.3</version> </plugin>
<plugin> <artifactId>maven-rar-plugin</artifactId> <version>2.2</version> </plugin> <plugin> <artifactId>maven-release-plugin</artifactId> <version>2.0-beta-8</version> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>2.3</version> </plugin>
<plugin> <artifactId>maven-site-plugin</artifactId> <version>2.0-beta-7</version> </plugin> <plugin> <artifactId>maven-source-plugin</artifactId> <version>2.0.4</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.4.3</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.1-alpha-2</version> </plugin> </plugins> </pluginManagement>
<plugins> <plugin> <artifactId>maven-help-plugin</artifactId> <version>2.1.1</version> </plugin> </plugins> </build>
<repositories> <repository> <snapshots> <enabled>false</enabled> </snapshots> <id>central</id> <name>Maven Repository Switchboard</name> <url>http://repo1.maven.org/maven2</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <releases> <updatePolicy>never</updatePolicy> </releases> <snapshots> <enabled>false</enabled> </snapshots> <id>central</id> <name>Maven Plugin Repository</name> <url>http://repo1.maven.org/maven2</url> </pluginRepository> </pluginRepositories> <reporting> <outputDirectory>C:\MVN\project\target/site</outputDirectory> </reporting> </project> |
在上面的pom.xml中,您可以看到Maven在执行所需目标时将使用的默认项目源文件夹结构,输出目录,所需插件,存储库,报告目录。
Maven pom.xml也不需要手动编写。 Maven提供了许多原型插件来创建项目,以便创建项目结构和pom.xml。
4 建立生命周期
什么是建立生命周期
构建生命周期是一个明确定义的阶段序列,它定义了要执行目标的顺序。 这里阶段代表生命周期的一个阶段。 作为一个例子,一个典型的Maven构建生命周期由以下几个阶段组成。
Phase(阶段) | Handles | Description |
prepare-resources | 资源复制 | 可以在此阶段自定义资源复制。 |
validate | 验证信息 | 验证项目是否正确以及是否有所有必要的信息。 |
compile | 编译 | 源代码编译在这个阶段完成。 |
Test | 测试 | 测试适合测试框架的编译源代码。 |
package | 打包 | 此阶段将创建JAR/WAR包,如POM.xml中的包装中所述。 |
install | 安装 | 这一阶段将软件包安装在本地/远程Maven仓库中。 |
Deploy | 部署 | 将最终包复制到远程存储库。 |
注册目标总是有前期和后期阶段,必须在特定阶段之前或之后运行。
当Maven开始构建项目时,它会逐步完成一个已定义的阶段序列并执行目标,这些目标将在每个阶段进行注册。
Maven有以下三种标准生命周期 -
clean
default(or build)
site
目标代表了一项有助于项目建设和管理的具体任务。 它可能会被绑定到零或更多的构建阶段。 不受任何构建阶段限制的目标可以通过直接调用在构建生命周期之外执行。
执行顺序取决于调用目标和构建阶段的顺序。 例如,请考虑下面的命令。 clean和package参数是构建阶段,而dependency:copy-dependencies是目标。
mvn clean dependency:copy-dependencies package |
这里首先执行clean阶段,然后是依赖项:copy-dependencies目标,最后将执行package阶段。
清除生命周期
当我们执行mvn post-clean命令时,Maven会调用由以下几个阶段组成的清理生命周期。
pre-clean
clean
post-clean
Maven的clean goal(clean:clean)必然会在清洁生命周期的清洁阶段。 它的clean:cleangoal通过删除构建目录来删除构建的输出。 因此,当执行mvn clean命令时,Maven会删除构建目录。
我们可以通过在清洁生命周期的上述任何阶段提及目标来定制此行为。
在以下示例中,我们将附加maven-antrun-plugin:将目标运行到预清理,清理和后清理阶段。 这将允许我们回显显示清洁生命周期阶段的文本消息。
我们在C:\ MVN \ project文件夹中创建了一个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>com.companyname.projectgroup</groupId> <artifactId>project</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>id.pre-clean</id> <phase>pre-clean</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>pre-clean phase</echo> </tasks> </configuration> </execution>
<execution> <id>id.clean</id> <phase>clean</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>clean phase</echo> </tasks> </configuration> </execution>
<execution> <id>id.post-clean</id> <phase>post-clean</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>post-clean phase</echo> </tasks> </configuration> </execution> </executions> </plugin> </plugins> </build> </project> |
现在打开命令控制台,转到包含pom.xml的文件夹并执行以下mvn命令。
C:\MVN\project>mvn post-clean |
Maven将开始处理和显示清洁生命周期的所有阶段。
[INFO] Scanning for projects... [INFO] ----------------------------------------------------------------- - [INFO] Building Unnamed - com.companyname.projectgroup:project:jar:1.0 [INFO] task-segment: [post-clean] [INFO] ------------------------------------------------------------------ [INFO] [antrun:run {execution: id.pre-clean}] [INFO] Executing tasks [echo] pre-clean phase [INFO] Executed tasks [INFO] [clean:clean {execution: default-clean}] [INFO] [antrun:run {execution: id.clean}] [INFO] Executing tasks [echo] clean phase [INFO] Executed tasks [INFO] [antrun:run {execution: id.post-clean}] [INFO] Executing tasks [echo] post-clean phase [INFO] Executed tasks [INFO] ------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------ [INFO] Total time: > 1 second [INFO] Finished at: Sat Jul 07 13:38:59 IST 2012 [INFO] Final Memory: 4M/44M [INFO] ------------------------------------------------------------------ |
您可以尝试调整mvn clean命令,该命令将显示预清理和清理。 后期清理阶段不会执行任何操作。
默认(或构建)生命周期
这是Maven的主要生命周期,用于构建应用程序。 它有以下23个阶段。
Sr.No. | Lifecycle Phase & Description |
1 | validate 验证项目是否正确,并且可以使用所有必要的信息来完成构建过程。 |
2 | initialize 初始化构建状态,例如设置属性。 |
3 | generate-sources 生成任何源代码以包含在编译阶段。 |
4 | process-sources 处理源代码,例如,过滤任何值。 |
5 | generate-resources 生成资源以包含在软件包中。 |
6 | process-resources 将资源复制并处理到目标目录,准备好进行打包阶段。 |
7 | compile 编译项目的源代码。 |
8 | process-classes 从编译后处理生成的文件,例如在Java类上进行字节码增强/优化。 |
9 | generate-test-sources 生成任何测试源代码以包含在编译阶段。 |
10 | process-test-sources 处理测试源代码,例如,过滤任何值。 |
11 | test-compile 将测试源代码编译到测试目标目录中。 |
12 | process-test-classes 处理从测试代码文件编译生成的文件。 |
13 | test 使用合适的单元测试框架运行测试(Junit就是其中之一)。 |
14 | prepare-package 在实际包装之前执行必要的准备包装的任何操作。 |
15 | package 获取编译后的代码并将其打包为可分发的格式,例如JAR,WAR或EAR文件。 |
16 | pre-integration-test 执行集成测试之前执行所需的操作。 例如,设置所需的环境。 |
17 | integration-test 如果需要,可将程序包处理并部署到可运行集成测试的环境中。 |
18 | post-integration-test 执行集成测试后执行所需的操作。 例如,清理环境。 |
19 | verify 运行任何检查来验证包是否有效并且符合质量标准。 |
20 | install 将软件包安装到本地存储库中,该存储库可以在本地用作其他项目的依赖项。 |
21 | deploy 将最终包复制到远程存储库,以便与其他开发人员和项目共享。 |
有几个与Maven生命周期有关的重要概念值得一提 -
当通过Maven命令调用某个阶段时,例如mvn compile,只会执行直到并包括该阶段的阶段。
根据包装的类型(JAR / WAR / EAR),不同的Maven目标将被绑定到Maven生命周期的不同阶段。
在以下示例中,我们将附加maven-antrun-plugin:将目标运行到Build生命周期的几个阶段。 这将允许我们回显显示生命周期阶段的文本消息。
我们已经在C:\ MVN \ project文件夹中更新了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>com.companyname.projectgroup</groupId> <artifactId>project</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>id.validate</id> <phase>validate</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>validate phase</echo> </tasks> </configuration> </execution>
<execution> <id>id.compile</id> <phase>compile</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>compile phase</echo> </tasks> </configuration> </execution>
<execution> <id>id.test</id> <phase>test</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>test phase</echo> </tasks> </configuration> </execution>
<execution> <id>id.package</id> <phase>package</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>package phase</echo> </tasks> </configuration> </execution>
<execution> <id>id.deploy</id> <phase>deploy</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>deploy phase</echo> </tasks> </configuration> </execution> </executions> </plugin> </plugins> </build></project> |
现在打开命令控制台,转到包含pom.xml的文件夹并执行以下mvn命令。
C:\MVN\project>mvn compile |
Maven将在编译阶段开始处理和显示构建生命周期的各个阶段。
[INFO] Scanning for projects... [INFO] ----------------------------------------------------------------- - [INFO] Building Unnamed - com.companyname.projectgroup:project:jar:1.0 [INFO] task-segment: [compile] [INFO] ----------------------------------------------------------------- - [INFO] [antrun:run {execution: id.validate}] [INFO] Executing tasks [echo] validate phase [INFO] Executed tasks [INFO] [resources:resources {execution: default-resources}] [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory C:\MVN\project\src\main\resources [INFO] [compiler:compile {execution: default-compile}] [INFO] Nothing to compile - all classes are up to date [INFO] [antrun:run {execution: id.compile}] [INFO] Executing tasks [echo] compile phase [INFO] Executed tasks [INFO] ----------------------------------------------------------------- - [INFO] BUILD SUCCESSFUL [INFO] ----------------------------------------------------------------- - [INFO] Total time: 2 seconds [INFO] Finished at: Sat Jul 07 20:18:25 IST 2012 [INFO] Final Memory: 7M/64M [INFO] ----------------------------------------------------------------- - |
Site 生命周期
Maven Site插件通常用于创建新文档以创建报告,部署网站等。它具有以下几个阶段 -
pre-site
site
post-site
site-deploy
在以下示例中,我们将附加maven-antrun-plugin:将目标运行到Site生命周期的所有阶段。 这将允许我们回显显示生命周期阶段的文本消息。
我们已经在C:\ MVN \ project文件夹中更新了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>com.companyname.projectgroup</groupId> <artifactId>project</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>id.pre-site</id> <phase>pre-site</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>pre-site phase</echo> </tasks> </configuration> </execution>
<execution> <id>id.site</id> <phase>site</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>site phase</echo> </tasks> </configuration> </execution>
<execution> <id>id.post-site</id> <phase>post-site</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>post-site phase</echo> </tasks> </configuration> </execution>
<execution> <id>id.site-deploy</id> <phase>site-deploy</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>site-deploy phase</echo> </tasks> </configuration> </execution>
</executions> </plugin> </plugins> </build> </project> |
现在打开命令控制台,转到包含pom.xml的文件夹并执行以下mvn命令。
C:\MVN\project>mvn site |
Maven将开始处理并显示站点生命周期的阶段,直至站点阶段。
[INFO] Scanning for projects... [INFO] ------------------------------------------------------------------ [INFO] Building Unnamed - com.companyname.projectgroup:project:jar:1.0 [INFO] task-segment: [site] [INFO] ------------------------------------------------------------------ [INFO] [antrun:run {execution: id.pre-site}] [INFO] Executing tasks [echo] pre-site phase [INFO] Executed tasks [INFO] [site:site {execution: default-site}]
[INFO] Generating "About" report. [INFO] Generating "Issue Tracking" report. [INFO] Generating "Project Team" report. [INFO] Generating "Dependencies" report. [INFO] Generating "Project Plugins" report. [INFO] Generating "Continuous Integration" report. [INFO] Generating "Source Repository" report. [INFO] Generating "Project License" report. [INFO] Generating "Mailing Lists" report. [INFO] Generating "Plugin Management" report. [INFO] Generating "Project Summary" report.
[INFO] [antrun:run {execution: id.site}] [INFO] Executing tasks [echo] site phase [INFO] Executed tasks [INFO] ------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------ [INFO] Total time: 3 seconds [INFO] Finished at: Sat Jul 07 15:25:10 IST 2012 [INFO] Final Memory: 24M/149M [INFO] ------------------------------------------------------------------ |
5 建立Profiles
什么是建立Profiles
构建配置文件是一组配置值,可用于设置或覆盖Maven构建的默认值。 使用构建配置文件,您可以为不同的环境定制构建,例如Production v / s开发环境。
配置文件在pom.xml文件中使用其activeProfiles / profiles元素指定,并以各种方式触发。 配置文件在构建时修改POM,并用于为参数提供不同的目标环境(例如,数据库服务器在开发,测试和生产环境中的路径)。
构建配置文件的类型
构建配置文件主要有三种类型。
Type | Where it is defined |
Per Project | 在项目POM文件pom.xml中定义 |
Per User | 在Maven settings.xml文件(%USER_HOME%/.m2 / settings.xml)中定义 |
Global | 在Maven全局设置xml文件中定义(%M2_HOME%/conf/settings.xml) |
配置文件激活
Maven构建配置文件可以以各种方式激活。
明确使用命令控制台输入。
通过maven设置。
基于环境变量(用户/系统变量)。
操作系统设置(例如,Windows系列)。
存在/丢失文件。
配置文件激活示例
让我们假设您的项目的以下目录结构 -
现在,在src / main / resources下,有三个特定于环境的文件 -
Sr.No. | File Name & Description |
1 | env.properties 如果未提及配置文件,则使用默认配置。 |
2 | env.test.properties 使用测试配置文件时测试配置。 |
3 | env.prod.properties 使用prod配置文件时的生产配置。 |
显式配置文件激活
在以下示例中,我们将附加maven-antrun-plugin:运行目标以测试阶段。 这将允许我们回复不同配置文件的文本消息。 我们将使用pom.xml来定义不同的配置文件,并使用maven命令在命令控制台激活配置文件。
假设,我们在C:\ MVN \ project文件夹中创建了以下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>com.companyname.projectgroup</groupId> <artifactId>project</artifactId> <version>1.0</version> <profiles> <profile> <id>test</id> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <phase>test</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>Using env.test.properties</echo> <copy file="src/main/resources/env.test.properties" tofile="${project.build.outputDirectory} /env.properties"/> </tasks> </configuration> </execution> </executions> </plugin> </plugins> </build> </profile> </profiles> </project> |
现在打开命令控制台,转到包含pom.xml的文件夹并执行以下mvn命令。 使用-P选项将配置文件名称作为参数传递。
C:\MVN\project>mvn test -Ptest |
Maven将开始处理并显示测试构建配置文件的结果。
[INFO] Scanning for projects... [INFO] ------------------------------------------------------------------ [INFO] Building Unnamed - com.companyname.projectgroup:project:jar:1.0 [INFO] task-segment: [test] [INFO] ------------------------------------------------------------------ [INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 3 resources [INFO] [compiler:compile {execution: default-compile}] [INFO] Nothing to compile - all classes are up to date [INFO] [resources:testResources {execution: default-testResources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\MVN\project\src\test\resources [INFO] [compiler:testCompile {execution: default-testCompile}] [INFO] Nothing to compile - all classes are up to date [INFO] [surefire:test {execution: default-test}] [INFO] Surefire report directory: C:\MVN\project\target\surefire-reports
------------------------------------------------------- T E S T S -------------------------------------------------------
There are no tests to run. Results : Tests run: 0, Failures: 0, Errors: 0, Skipped: 0 [INFO] [antrun:run {execution: default}] [INFO] Executing tasks [echo] Using env.test.properties [INFO] Executed tasks
[INFO] ------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------
[INFO] Total time: 1 second [INFO] Finished at: Sun Jul 08 14:55:41 IST 2012 [INFO] Final Memory: 8M/64M [INFO] ------------------------------------------------------------------ |
现在作为练习,您可以执行以下步骤 -
将另一个配置文件元素添加到pom.xml的配置文件元素(复制现有配置文件元素并将其粘贴到配置文件元素结束位置)
将此配置文件元素的ID从测试更新为正常。
更新任务部分以回显env.properties并将env.properties复制到目标目录。
再次重复上述三个步骤,将id更新为env.prod.properties的prod和task部分。
就这样。 现在你已经准备好三个构建配置文件(正常/测试/产品)。
现在打开命令控制台,转到包含pom.xml的文件夹并执行以下mvn命令。 使用-P选项将配置文件名称作为参数传递。
C:\MVN\project>mvn test -Pnormal
C:\MVN\project>mvn test -Pprod |
检查构建的输出以查看差异。
通过Maven设置激活配置文件
打开Maven settings.xml文件,该文件在%USER_HOME%/。m2目录中可用,其中%USER_HOME%表示用户主目录。 如果settings.xml文件不存在,则创建一个新文件。
使用活动配置文件节点将测试配置文件添加为活动配置文件,如示例中所示。
<settings 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/settings-1.0.0.xsd"> <mirrors> <mirror> <id>maven.dev.snaponglobal.com</id> <name>Internal Artifactory Maven repository</name> <url>http://repo1.maven.org/maven2/</url> <mirrorOf>*</mirrorOf> </mirror> </mirrors> <activeProfiles> <activeProfile>test</activeProfile> </activeProfiles> </settings> |
现在打开命令控制台,转到包含pom.xml的文件夹并执行以下mvn命令。 不要使用-P选项传递配置文件名称。 Maven将显示测试配置文件的结果为活动配置文件。
C:\MVN\project>mvn test |
现在从maven settings.xml中删除活动配置文件并更新pom.xml中提到的测试配置文件。 将激活元素添加到配置文件元素,如下所示。
当系统属性“env”用值“test”指定时,将触发测试配置文件。 创建一个环境变量“env”并将其值设置为“test”。
<profile> <id>test</id> <activation> <property> <name>env</name> <value>test</value> </property> </activation> </profile> |
让我们打开命令控制台,转到包含pom.xml的文件夹并执行以下mvn命令。
C:\MVN\project>mvn test |
通过操作系统激活配置文件
激活元素包含os细节,如下所示。 当系统是Windows XP时,此测试配置文件将触发。
<profile> <id>test</id> <activation> <os> <name>Windows XP</name> <family>Windows</family> <arch>x86</arch> <version>5.1.2600</version> </os> </activation> </profile> |
现在打开命令控制台,转到包含pom.xml的文件夹并执行以下mvn命令。 不要使用-P选项传递配置文件名称。 Maven将显示测试配置文件的结果为活动配置文件。
C:\MVN\project>mvn test |
通过当前/缺失文件激活配置文件
现在激活元素包含操作系统细节,如下所示。 当target / generated-sources / axistools / wsdl2java / com / companyname / group丢失时,将触发测试配置文件。
<profile> <id>test</id> <activation> <file> <missing>target/generated-sources/axistools/wsdl2java/ com/companyname/group</missing> </file> </activation> </profile> |
现在打开命令控制台,转到包含pom.xml的文件夹并执行以下mvn命令。 不要使用-P选项传递配置文件名称。 Maven将显示测试配置文件的结果为活动配置文件。
C:\MVN\project>mvn test |
6 仓库
什么是Maven仓库
在Maven术语中,仓库是一个目录,其中存储了所有项目jar,lib jar,插件或任何其他特定于项目的工件,并且可以轻松地由Maven使用。
Maven存储库有三种类型。下面的插图将给出了这三种类型。
本地
中央
远程
本地仓库
Maven本地存储库是您计算机上的文件夹位置。它在第一次运行任何maven命令时被创建。
Maven本地存储库保持你项目的所有依赖(库jars,插件jar等)。当您运行Maven构建时,Maven会自动将所有依赖项jar下载到本地存储库中。它有助于避免每次构建项目时引用远程计算机上存储的依赖项。
默认情况下,Maven本地存储库是由Maven在%USER_HOME%目录中创建的。要覆盖默认位置,请在%M2_HOME%\ conf目录中提供的Maven settings.xml文件中提及另一个路径。
<settings xmlns = "http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <localRepository>C:/MyLocalRepository</localRepository> </settings> |
当您运行Maven命令时,Maven会将依赖关系下载到您的自定义路径中。
中央仓库
Maven中央存储库是由Maven社区提供的存储库。它包含大量常用的库。
当Maven在本地存储库中找不到任何依赖项时,它会使用以下URL在中央存储库中开始搜索 - https://repo1.maven.org/maven2/
中央存储库的关键概念如下 -
该存储库由Maven社区管理。
不需要配置。
它需要搜索互联网。
为了浏览中央Maven仓库的内容,Maven社区提供了一个URL - https://search.maven.org/#browse。使用这个库,开发人员可以搜索中央存储库中的所有可用库。
远程仓库
有时,Maven在中央存储库中也找不到所提到的依赖项。然后停止构建过程并将错误消息输出到控制台。为了防止出现这种情况,Maven提供了Remote Repository的概念,它是开发人员自己的定制存储库,包含所需的库或其他项目jar。
例如,使用下面提到的POM.xml,Maven将从同一个pom.xml中提到的Remote Repositories下载依赖项(在中央存储库中不可用)。
<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.companyname.projectgroup</groupId> <artifactId>project</artifactId> <version>1.0</version> <dependencies> <dependency> <groupId>com.companyname.common-lib</groupId> <artifactId>common-lib</artifactId> <version>1.0.0</version> </dependency> <dependencies> <repositories> <repository> <id>companyname.lib1</id> <url>http://download.companyname.org/maven2/lib1</url> </repository> <repository> <id>companyname.lib2</id> <url>http://download.companyname.org/maven2/lib2</url> </repository> </repositories> </project> |
Maven依赖搜索序列
当我们执行Maven构建命令时,Maven开始按以下顺序查找依赖库 -
步骤1 - 在本地存储库中搜索依赖关系,如果未找到,则转到步骤2,否则执行进一步处理。
第2步 - 在中央存储库中搜索依赖关系,如果未找到并且提及远程存储库/存储库,则转到第4步。否则,将其下载到本地存储库供将来参考。
第3步 - 如果没有提到远程存储库,Maven会停止处理并抛出错误(无法找到依赖关系)。
步骤4 - 在远程存储库或存储库中搜索依赖关系,如果找到,则将其下载到本地存储库供将来参考。否则,Maven会停止处理并抛出错误(无法找到依赖项)。
7 插件(Plugins)
什么是Maven插件
Maven实际上是一个插件执行框架,其中每个任务实际上都是由插件完成的。Maven插件通常用于 -
创建jar文件
创建war文件
编译代码文件
代码的单元测试
创建项目文档
创建项目报告
插件通常提供一组目标,可以使用以下语法执行 -
mvn [plugin-name]:[goal-name] |
例如,通过运行以下命令,可以使用maven-compiler-plugin的编译目标编译Java项目。
mvn compiler:compile |
插件类型
Maven提供了以下两种插件 -
Sr.No. | 类型和说明 |
1 | 构建插件 它们在构建过程中执行,应该在pom.xml的<build />元素中进行配置。 |
2 | 报告插件 它们在网站生成过程中执行,并且应该在pom.xml的<reporting />元素中进行配置。 |
以下是几个常见插件的列表 -
Sr.No. | 插件和说明 |
1 | clean 构建完成后清理目标。删除目标目录。 |
2 | Compiler 编译Java源文件。 |
3 | Surefire 运行JUnit单元测试。创建测试报告。 |
4 | Jar 从当前项目构建JAR文件。 |
5 | War 从当前项目构建WAR文件。 |
6 | javadoc 为项目生成Javadoc。 |
7 | antrun 从构建的任何阶段运行一组ant任务。 |
例
我们在示例中广泛使用了maven-antrun-plugin来在控制台上打印数据。参考构建配置文件一章 让我们以更好的方式理解它,并在C:\ MVN \ project文件夹中创建一个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>com.companyname.projectgroup</groupId> <artifactId>project</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>id.clean</id> <phase>clean</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>clean phase</echo> </tasks> </configuration> </execution> </executions> </plugin> </plugins> </build> </project> |
接下来,打开命令控制台并转至包含pom.xml的文件夹并执行以下mvn命令。
C:\MVN\project>mvn clean |
Maven将开始处理和显示清洁生命周期的清洁阶段。
[INFO] Scanning for projects... [INFO] ------------------------------------------------------------------ [INFO] Building Unnamed - com.companyname.projectgroup:project:jar:1.0 [INFO] task-segment: [post-clean] [INFO] ------------------------------------------------------------------ [INFO] [clean:clean {execution: default-clean}] [INFO] [antrun:run {execution: id.clean}] [INFO] Executing tasks [echo] clean phase [INFO] Executed tasks [INFO] ------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------ [INFO] Total time: < 1 second [INFO] Finished at: Sat Jul 07 13:38:59 IST 2012 [INFO] Final Memory: 4M/44M [INFO] ------------------------------------------------------------------ |
上面的例子说明了以下关键概念 -
插件在pom.xml中使用插件元素指定。
每个插件可以有多个目标。
您可以使用其相位元素来定义插件应从何处开始处理的阶段。我们已经使用了clean阶段。
您可以通过将任务绑定到插件的目标来配置要执行的任务。我们将echo任务与maven-antrun-plugin的run目标绑定在一起。
如果Maven在本地存储库中不可用,Maven将下载该插件并开始处理。
8 创建项目
Maven使用原型插件来创建项目。为了创建一个简单的Java应用程序,我们将使用maven-archetype-quickstart插件。在下面的例子中,我们将在C:\ MVN文件夹中创建一个基于maven的java应用程序项目。
让我们打开命令控制台,进入C:\ MVN目录并执行以下mvn命令。
C:\MVN>mvn archetype:generate -DgroupId = com.companyname.bank -DartifactId = consumerBanking -DarchetypeArtifactId = maven-archetype-quickstart -DinteractiveMode = false |
Maven将开始处理并创建完整的Java应用程序项目结构。
[INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'archetype'. [INFO] ------------------------------------------------------------------- [INFO] Building Maven Default Project [INFO] task-segment: [archetype:generate] (aggregator-style) [INFO] ------------------------------------------------------------------- [INFO] Preparing archetype:generate [INFO] No goals needed for project - skipping [INFO] [archetype:generate {execution: default-cli}] [INFO] Generating project in Batch mode [INFO] ------------------------------------------------------------------- [INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.0 [INFO] -------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.companyname.bank [INFO] Parameter: packageName, Value: com.companyname.bank [INFO] Parameter: package, Value: com.companyname.bank [INFO] Parameter: artifactId, Value: consumerBanking [INFO] Parameter: basedir, Value: C:\MVN [INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: C:\MVN\consumerBanking [INFO] ------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------ [INFO] Total time: 14 seconds [INFO] Finished at: Tue Jul 10 15:38:58 IST 2012 [INFO] Final Memory: 21M/124M [INFO] ------------------------------------------------------------------ |
现在转到C:/ MVN目录。您将看到一个名为consumer Banking的java应用程序项目(如artifactId中指定的)。Maven使用如下所示的标准目录布局 -
使用上面的例子,我们可以理解以下关键概念 -
Sr.No. | 文件夹结构和说明 |
1 | consumerBanking 包含src文件夹和pom.xml |
2 | src/main/java 在包结构(com/companyName/bank)下包含java代码文件。 |
3 | src/main/test 包含包结构(com/companyName/bank)下的测试java代码文件。 |
4 | src/main/resources 它包含图像/属性文件(在上面的例子中,我们需要手动创建这个结构)。 |
如果您观察,您会发现Maven还创建了一个示例Java源文件和Java测试文件。打开C:\ MVN \ consumerBanking \ src \ main \ java \ com \ companyname \ bank文件夹,您会看到App.java。
package com.companyname.bank;
/** * Hello world! * */ public class App { public static void main( String[] args ){ System.out.println( "Hello World!" ); } } |
打开C:\ MVN \ consumerBanking \ src \ test \ java \ com \ companyname \ bank文件夹以查看AppTest.java。
package com.companyname.bank;
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 ); } } |
开发人员需要如上表中所述放置文件,Maven处理所有与构建相关的复杂问题。
在下一章中,我们将讨论如何使用Maven构建和测试项目来构建和测试项目。
9 构建和测试项目
我们在Project Creation章节学到的是如何使用Maven创建Java应用程序。现在我们将看到如何构建和测试应用程序。
转到创建您的Java应用程序的C:/ MVN目录。打开consumerBanking文件夹。您将看到包含以下内容的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>com.companyname.projectgroup</groupId> <artifactId>project</artifactId> <version>1.0</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> </dependency> </dependencies> </project> |
在这里你可以看到,Maven已经添加了Junit作为测试框架。默认情况下,Maven会在其默认目录结构中添加一个源文件App.java和一个测试文件AppTest.java,如前一章所述。
让我们打开命令控制台,进入C:\ MVN \ consumerBanking目录并执行以下mvn命令。
C:\MVN\consumerBanking>mvn clean package |
Maven将开始构建该项目。
[INFO] Scanning for projects... [INFO] ------------------------------------------------------------------- [INFO] Building consumerBanking [INFO] task-segment: [clean, package] [INFO] ------------------------------------------------------------------- [INFO] [clean:clean {execution: default-clean}] [INFO] Deleting directory C:\MVN\consumerBanking\target [INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\MVN\consumerBanking\src\main\resources [INFO] [compiler:compile {execution: default-compile}] [INFO] Compiling 1 source file to C:\MVN\consumerBanking\target\classes [INFO] [resources:testResources {execution: default-testResources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\MVN\consumerBanking\src\test\resources [INFO] [compiler:testCompile {execution: default-testCompile}] [INFO] Compiling 1 source file to C:\MVN\consumerBanking\target\test-classes [INFO] [surefire:test {execution: default-test}] [INFO] Surefire report directory: C:\MVN\consumerBanking\target\surefire-reports
----------------------------------------------------- T E S T S -----------------------------------------------------
Running com.companyname.bank.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.027 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] [jar:jar {execution: default-jar}] [INFO] Building jar: C:\MVN\consumerBanking\target\ consumerBanking-1.0-SNAPSHOT.jar
[INFO]----------------------------------------------- [INFO] BUILD SUCCESSFUL [INFO]-----------------------------------------------
[INFO] Total time: 2 seconds [INFO] Finished at: Tue Jul 10 16:52:18 IST 2012 [INFO] Final Memory: 16M/89M [INFO]----------------------------------------------- |
您已经构建了您的项目并创建了最终的jar文件,以下是关键的学习概念 -
我们给maven两个目标,首先清理目标目录(clean),然后将项目生成输出打包为jar(包)。
作为consumerBanking-1.0-SNAPSHOT.jar,包装的jar文件在consumerBanking \ target文件夹中可用。
测试报告可在consumerBanking \ target \ surefire-reports文件夹中找到。
Maven编译源代码文件,然后测试源代码文件。
然后Maven运行测试用例。
最后,Maven创建包。
现在打开命令控制台,进入C:\ MVN \ consumerBanking \ target \ classes目录并执行以下java命令。
>java com.companyname.bank.App |
你会看到如下结果 -
Hello World! |
添加Java源文件
让我们看看我们如何在我们的项目中添加额外的Java文件。打开C:\ MVN \ consumerBanking \ src \ main \ java \ com \ companyname \ bank文件夹,在Util.java中创建Util类。
package com.companyname.bank;
public class Util { public static void printMessage(String message){ System.out.println(message); } } |
更新App类以使用Util类。
package com.companyname.bank;
/** * Hello world! * */
public class App { public static void main( String[] args ){ Util.printMessage("Hello World!"); } } |
现在打开命令控制台,进入C:\ MVN \ consumerBanking目录并执行以下mvn命令。
>mvn clean compile |
Maven构建成功后,转至C:\ MVN \ consumerBanking \ target \ classes目录并执行以下java命令。
>java -cp com.companyname.bank.App |
你会看到如下结果 -
Hello World! |
10 外部依赖
如您所知,Maven使用存储库的概念进行依赖关系管理。但是如果依赖在任何远程存储库和中央存储库中都不可用,会发生什么情况?Maven使用External Dependency的概念为这种情况提供了答案。
例如,让我们对'创建Java项目'一章中创建的项目进行以下更改。
将lib文件夹添加到src文件夹。
将任何jar复制到lib文件夹中。我们使用了ldapjdk.jar,它是LDAP操作的助手库。
现在我们的项目结构应该如下所示 -
在这里,你有自己的库,专门针对项目,这是一个常见的案例,它包含罐子,可能无法在任何仓库供任何仓库供Maven下载。如果你的代码在Maven中使用这个库,那么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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.bank</groupId> <artifactId>consumerBanking</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>consumerBanking</name> <url>http://maven.apache.org</url>
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency>
<dependency> <groupId>ldapjdk</groupId> <artifactId>ldapjdk</artifactId> <scope>system</scope> <version>1.0</version> <systemPath>${basedir}\src\lib\ldapjdk.jar</systemPath> </dependency> </dependencies>
</project> |
在上面的例子中查看依赖项下的第二个依赖项元素,它清除了以下关于外部依赖项的关键概念。
外部依赖(库jar位置)可以在pom.xml中以与其他依赖相同的方式配置。
指定groupId与库的名称相同。
指定artifactId与库的名称相同。
将范围指定为系统。
指定相对于项目位置的系统路径。
希望现在你清楚了解外部依赖关系,并且您将能够在Maven项目中指定外部依赖关系。
11 项目文档
本教程将教你如何一次性创建应用程序的文档。所以让我们开始吧,使用前面章节中给出的例子,到C:\ MVN目录中创建您的Java consumerBanking应用程序。打开consumerBanking文件夹并执行以下mvn命令。
C:\MVN>mvn site |
Maven将开始构建该项目。
[INFO] Scanning for projects... [INFO]----------------------------------------------- [INFO] Building consumerBanking [INFO] task-segment: [site] [INFO]----------------------------------------------- [INFO] [site:site {execution: default-site}] [INFO] artifact org.apache.maven.skins:maven-default-skin: checking for updates from central
[INFO] Generating "About" report. [INFO] Generating "Issue Tracking" report. [INFO] Generating "Project Team" report. [INFO] Generating "Dependencies" report. [INFO] Generating "Continuous Integration" report. [INFO] Generating "Source Repository" report. [INFO] Generating "Project License" report. [INFO] Generating "Mailing Lists" report. [INFO] Generating "Plugin Management" report. [INFO] Generating "Project Summary" report.
[INFO]----------------------------------------------- [INFO] BUILD SUCCESSFUL [INFO]-----------------------------------------------
[INFO] Total time: 16 seconds [INFO] Finished at: Wed Jul 11 18:11:18 IST 2012 [INFO] Final Memory: 23M/148M [INFO]----------------------------------------------- |
您的项目文档已准备就绪。Maven在目标目录中创建了一个站点。
打开C:\ MVN \ consumerBanking \ target \ site文件夹。点击index.html查看文档。
Maven使用称为Doxia的文档处理引擎创建文档,该引擎将多种源格式读入通用文档模型。要为您的项目编写文档,您可以使用由Doxia解析的以下几种常用格式编写内容。
格式名称 | 描述 | 参考 |
XDOC | Maven 1.x文档格式 | |
FML | 用于FAQ文档 |
12 项目模板
Maven使用Archetype的概念为用户提供了一个非常大的不同类型的项目模板列表(数字614)。Maven使用以下命令帮助用户快速启动一个新的Java项目。
mvn archetype:generate |
什么是原型?
Archetype是一个Maven插件,其任务是根据其模板创建项目结构。我们将使用quickstart archetype插件在这里创建一个简单的Java应用程序。
使用项目模板
让我们打开命令控制台,进入C:\> MVN目录并执行以下mvn命令。
C:\MVN>mvn archetype:generate |
Maven将开始处理,并要求选择所需的原型。
[INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'archetype'. [INFO] ------------------------------------------------------------------- [INFO] Building Maven Default Project [INFO] task-segment: [archetype:generate] (aggregator-style) [INFO] ------------------------------------------------------------------- [INFO] Preparing archetype:generate ...
600: remote −> org.trailsframework:trails-archetype (-) 601: remote −> org.trailsframework:trails-secure-archetype (-) 602: remote −> org.tynamo:tynamo-archetype (-) 603: remote −> org.wicketstuff.scala:wicket-scala-archetype (-) 604: remote −> org.wicketstuff.scala:wicketstuff-scala-archetype
Basic setup for a project that combines Scala and Wicket, depending on the Wicket-Scala project. Includes an example Specs test.)
605: remote −> org.wikbook:wikbook.archetype (-) 606: remote −> org.xaloon.archetype:xaloon-archetype-wicket-jpa-glassfish (-) 607: remote −> org.xaloon.archetype:xaloon-archetype-wicket-jpa-spring (-) 608: remote −> org.xwiki.commons:xwiki-commons-component-archetype (Make it easy to create a maven project for creating XWiki Components.) 609: remote −> org.xwiki.rendering:xwiki-rendering-archetype-macro (Make it easy to create a maven project for creating XWiki Rendering Macros.) 610: remote −> org.zkoss:zk-archetype-component (The ZK Component archetype) 611: remote −> org.zkoss:zk-archetype-webapp (The ZK wepapp archetype) 612: remote −> ru.circumflex:circumflex-archetype (-) 613: remote −> se.vgregion.javg.maven.archetypes:javg-minimal-archetype (-) 614: remote −> sk.seges.sesam:sesam-annotation-archetype (-) Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 203: |
按Enter键选择默认选项(203:maven-archetype-quickstart)
Maven会要求特定版本的原型。
Choose org.apache.maven.archetypes:maven-archetype-quickstart version: 1: 1.0-alpha-1 2: 1.0-alpha-2 3: 1.0-alpha-3 4: 1.0-alpha-4 5: 1.0 6: 1.1 Choose a number: 6: |
按Enter键选择默认选项(6:maven-archetype-quickstart:1.1)
Maven会询问项目的细节。按要求输入项目详细信息。如果提供了默认值,请按Enter键。您可以通过输入自己的值来覆盖它们。
Define value for property 'groupId': : com.companyname.insurance Define value for property 'artifactId': : health Define value for property 'version': 1.0-SNAPSHOT: Define value for property 'package': com.companyname.insurance: |
Maven会要求项目详细确认。按回车键或按Y.
Confirm properties configuration: groupId: com.companyname.insurance artifactId: health version: 1.0-SNAPSHOT package: com.companyname.insurance Y: |
现在Maven将开始创建项目结构并显示以下内容 -
[INFO]----------------------------------------------- [INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.1 [INFO]-----------------------------------------------
[INFO] Parameter: groupId, Value: com.companyname.insurance [INFO] Parameter: packageName, Value: com.companyname.insurance [INFO] Parameter: package, Value: com.companyname.insurance [INFO] Parameter: artifactId, Value: health [INFO] Parameter: basedir, Value: C:\MVN [INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: C:\MVN\health [INFO]----------------------------------------------- [INFO] BUILD SUCCESSFUL [INFO]----------------------------------------------- [INFO] Total time: 4 minutes 12 seconds [INFO] Finished at: Fri Jul 13 11:10:12 IST 2012 [INFO] Final Memory: 20M/90M [INFO]----------------------------------------------- |
创建项目
现在转到C:\> MVN目录。您会看到一个名为health的java应用程序项目,它在项目创建时被赋予artifactId。Maven将为该项目创建一个标准的目录布局,如下所示 -
创建POM.xml
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>com.companyname.insurance</groupId> <artifactId>health</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>health</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> |
创建App.java
Maven如下所示为该项目生成示例Java源文件App.java -
位置:C:\> MVN> health> src> main> java> com> companyname> insurance> App.java。
package com.companyname.insurance;
/** * Hello world! * */ public class App { public static void main( String[] args ) { System.out.println( "Hello World!" ); } } |
创建AppTest.java
Maven为该项目生成示例Java源测试文件AppTest.java,如下所示 -
位置:C:\> MVN>健康> src>测试> java> com>公司名称>保险> AppTest.java。
package com.companyname.insurance;
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 ); } } |
现在你可以看到Maven的力量。您可以在maven中使用单个命令创建任何类型的项目,并可以启动您的开发。
Sr.No. | 原型ArtifactIds&Description |
1 | maven-archetype-archetype 一个原型,其中包含一个示例原型。 |
2 | maven-archetype-j2ee-simple 一个原型,其中包含一个简化的示例J2EE应用程序。 |
3 | maven-archetype-mojo 一个原型,其中包含一个示例Maven插件示例。 |
4 | maven-archetype-plugin 一个原型,其中包含一个示例Maven插件。 |
5 | maven-archetype-plugin-site 一个原型,其中包含一个示例Maven插件网站。 |
6 | maven-archetype-portlet 包含示例JSR-268 Portlet的原型。 |
7 | maven-archetype-quickstart 一个原型,其中包含一个示例Maven项目。 |
8 | maven-archetype-simple 一个原型,其中包含一个简单的Maven项目。 |
9 | maven-archetype-site 一个原型,其中包含一个示例Maven站点,用于演示APT,XDoc和FML等一些受支持的文档类型,并演示如何在您的网站上进行操作。 |
10 | maven-archetype-site-simple 一个原型,其中包含一个示例Maven网站。 |
11 | maven-archetype-webapp 一个原型,其中包含一个示例Maven Webapp项目。 |
13 快照
一个大型软件应用程序通常由多个模块组成,这是多个团队在同一应用程序的不同模块上工作的常见情形。例如,考虑一个团队正在将应用程序的前端作为app-ui项目(app-ui.jar:1.0)并且他们正在使用数据服务项目(data-service.jar:1.0)。
现在可能发生的事情是,处理数据服务的团队正在快速修复或增强功能,他们几乎每隔一天都会将库发布到远程存储库。
现在,如果数据服务团队每隔一天上传一个新版本,则会出现以下问题 -
数据服务团队每次发布更新的代码时都应该告诉app-ui团队。
app-ui团队需要定期更新他们的pom.xml以获取更新版本。
为了处理这种情况,SNAPSHOT概念发挥作用。
什么是SNAPSHOT?
SNAPSHOT是指示当前开发副本的特殊版本。与常规版本不同,Maven会在每个版本的远程存储库中检查新的SNAPSHOT版本。
现在数据服务团队将每次发布SNAPSHOT的更新代码到数据库中,例如数据服务:1.0-SNAPSHOT,替换旧的SNAPSHOT jar。
快照vs版本
在版本的情况下,如果Maven曾经下载过所提到的版本,比如说data-service:1.0,它永远不会尝试下载版本库中的新版本1.0。要下载更新的代码,数据服务版本将升级到1.1。
在SNAPSHOT的情况下,每次app-ui团队构建项目时,Maven都会自动获取最新的SNAPSHOT(数据服务:1.0-SNAPSHOT)。
app-ui pom.xml
app-ui项目正在使用1.0-SNAPSHOT的数据服务。
<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>app-ui</groupId> <artifactId>app-ui</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>health</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>data-service</groupId> <artifactId>data-service</artifactId> <version>1.0-SNAPSHOT</version> <scope>test</scope> </dependency> </dependencies> </project> |
data-service pom.xml
data-service项目正在发布1.0-SNAPSHOT用于每一次小的更改。
<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>data-service</groupId> <artifactId>data-service</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>health</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> </project> |
尽管在SNAPSHOT的情况下,Maven每天都会自动获取最新的SNAPSHOT,但您可以使用-U切换到任何maven命令来强制maven下载最新的快照构建。
mvn clean package -U |
让我们打开命令控制台,进入C:\> MVN> app-ui目录并执行以下mvn命令。
C:\MVN\app-ui>mvn clean package -U |
Maven将在下载最新的SNAPSHOT数据服务后开始构建项目。
[INFO] Scanning for projects... [INFO]-------------------------------------------- [INFO] Building consumerBanking [INFO] task-segment: [clean, package] [INFO]-------------------------------------------- [INFO] Downloading data-service:1.0-SNAPSHOT [INFO] 290K downloaded. [INFO] [clean:clean {execution: default-clean}] [INFO] Deleting directory C:\MVN\app-ui\target [INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\MVN\app-ui\src\main\resources [INFO] [compiler:compile {execution:default-compile}] [INFO] Compiling 1 source file to C:\MVN\app-ui\target\classes [INFO] [resources:testResources {execution: default-testResources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\MVN\app-ui\src\test\resources [INFO] [compiler:testCompile {execution: default-testCompile}] [INFO] Compiling 1 source file to C:\MVN\app-ui\target\test-classes [INFO] [surefire:test {execution: default-test}] [INFO] Surefire report directory: C:\MVN\app-ui\target\ surefire-reports
-------------------------------------------------- T E S T S --------------------------------------------------
Running com.companyname.bank.AppTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.027 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] [jar:jar {execution: default-jar}] [INFO] Building jar: C:\MVN\app-ui\target\ app-ui-1.0-SNAPSHOT.jar [INFO]-------------------------------------------------------- [INFO] BUILD SUCCESSFUL [INFO]-------------------------------------------------------- [INFO] Total time: 2 seconds [INFO] Finished at: 2015-09-27T12:30:02+05:30 [INFO] Final Memory: 16M/89M [INFO]------------------------------------------------------------------------ |
14 构建自动化
Build Automation定义了项目构建成功完成后依赖项目构建过程开始的场景,以确保依赖项目是稳定的。
例
考虑一个团队正在开发一个项目bus-core-api,其中两个其他项目app-web-ui和app-desktop-ui都依赖于该项目。
app-web-ui项目正在使用bus-core-api项目的1.0-SNAPSHOT 。
<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>app-web-ui</groupId> <artifactId>app-web-ui</artifactId> <version>1.0</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>bus-core-api</groupId> <artifactId>bus-core-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project> |
app-desktop-ui项目正在使用1.0-SNAPSHOT的bus-core-api项目。
<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>app_desktop_ui</groupId> <artifactId>app_desktop_ui</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>app_desktop_ui</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> <dependency> <groupId>bus_core_api</groupId> <artifactId>bus_core_api</artifactId> <version>1.0-SNAPSHOT</version> <scope>system</scope> <systemPath>C:\MVN\bus_core_api\target\bus_core_api-1.0-SNAPSHOT.jar</systemPath> </dependency> </dependencies> </project> |
bus-core-api项目 -
<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>bus_core_api</groupId> <artifactId>bus_core_api</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> </project> |
现在,app-web-ui和app-desktop-ui项目团队要求每当bus-core-api项目发生变化时,他们的构建过程都应该启动。
通过使用快照,确保应该使用最新的bus-core-api项目,但为了满足上述要求,我们需要额外做一些事情。
我们可以采取以下两种方式 -
在bus-core-api pom中添加一个构建后的目标,以启动app-web-ui和app-desktop-ui构建。
使用像Hudson这样的持续集成(CI)服务器来自动管理构建自动化。
使用Maven
更新bus-core-api项目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>bus-core-api</groupId> <artifactId>bus-core-api</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <build> <plugins> <plugin> <artifactId>maven-invoker-plugin</artifactId> <version>1.6</version> <configuration> <debug>true</debug> <pomIncludes> <pomInclude>app-web-ui/pom.xml</pomInclude> <pomInclude>app-desktop-ui/pom.xml</pomInclude> </pomIncludes> </configuration> <executions> <execution> <id>build</id> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin> </plugins> <build> </project> |
让我们打开命令控制台,进入C:\> MVN> bus-core-api目录并执行以下mvn命令。
>mvn clean package -U |
Maven将开始构建项目bus-core-api。
[INFO] Scanning for projects... [INFO] ------------------------------------------------------------------ [INFO] Building bus-core-api [INFO] task-segment: [clean, package] [INFO] ------------------------------------------------------------------ ... [INFO] [jar:jar {execution: default-jar}] [INFO] Building jar: C:\MVN\bus-core-ui\target\ bus-core-ui-1.0-SNAPSHOT.jar [INFO] ------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------ |
一旦bus-core-api构建成功,Maven将开始构建app-web-ui项目。
[INFO] ------------------------------------------------------------------ [INFO] Building app-web-ui [INFO] task-segment: [package] [INFO] ------------------------------------------------------------------ ... [INFO] [jar:jar {execution: default-jar}] [INFO] Building jar: C:\MVN\app-web-ui\target\ app-web-ui-1.0-SNAPSHOT.jar [INFO] ------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------ |
一旦app-web-ui构建成功,Maven将开始构建app-desktop-ui项目。
[INFO] ------------------------------------------------------------------ [INFO] Building app-desktop-ui [INFO] task-segment: [package] [INFO] ------------------------------------------------------------------ ... [INFO] [jar:jar {execution: default-jar}] [INFO] Building jar: C:\MVN\app-desktop-ui\target\ app-desktop-ui-1.0-SNAPSHOT.jar [INFO] ------------------------------------------------------------------- [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------- |
通过Maven使用持续集成服务
开发人员更喜欢使用CI服务器。每次添加新项目(例如,app-mobile-ui)时,不需要更新bus-core-api项目作为bus-core-api项目的依赖项目。Hudsion是一个用java编写的持续集成工具,它在一个servlet容器中,例如Apache tomcat和glassfish应用服务器。Hudson使用Maven依赖管理自动管理构建自动化。以下快照将定义Hudson工具的角色。
哈德森认为每个项目都是工作。一旦项目代码签入SVN(或映射到Hudson的任何源代码管理工具),Hudson就开始构建作业,一旦完成此作业,它将自动启动其他相关作业(其他相关项目)。
在上面的例子中,当在SVN中更新bus-core-ui源代码时,Hudson开始构建。一旦构建成功,Hudson会自动查找依赖项目,并开始构建app-web-ui和app-desktop-ui项目。
15 管理依赖关系
Maven的核心功能之一是依赖管理。一旦我们需要处理多模块项目(由数百个模块/子项目组成),管理依赖关系是一项艰巨的任务。Maven提供高度的控制来管理这些场景。
传递依赖关系
通常情况下,当一个lib(比如说A)依赖于其他lib(比如B)时,如果另一个项目C想要使用A,那么该项目也需要使用lib B。
Maven帮助避免发现所有需要的库的需求。Maven通过读取依赖关系的项目文件(pom.xml),自动找出它们的依赖关系。
我们只需要在每个项目中定义直接依赖关系。Maven自动处理剩下的部分。
通过传递依赖关系,包含lib的图形可以在很大程度上快速增长。存在重复库时可能会出现这种情况。Maven提供了一些功能来控制传递依赖的程度。
Sr.No. | 功能和说明 |
1 | 依赖调解 确定在遇到多个版本的工件时要使用哪个版本的依赖关系。如果两个依赖版本在依赖关系树中处于相同深度,则将使用第一个声明的依赖关系。 |
2 | 依赖管理 直接指定在传递依赖关系中遇到的jar的版本。举一个例子,项目C可以在其依赖关系管理部分中包含B作为依赖关系,并直接控制何时引用B的哪个版本。 |
3 | 依赖范围 按照构建的当前阶段包含依赖项。 |
4 | 排除的依赖关系 任何传递依赖可以使用“exclusion”元素排除。例如,A依赖B而B依赖C,则A可以将C标记为排除。 |
5 | 可选的依赖关系 使用“optional”元素可将任何传递依赖项标记为可选项。例如,A依赖B,而B依赖C.现在B将C标记为可选。那么A不会使用C. |
依赖范围
发现传递性依赖关系可以使用各种依赖性范围进行限制,如下所述。
Sr.No. | 范围和说明 |
1 | compile 这个范围表示依赖项在项目的类路径中可用。它是默认范围。 |
2 | provided 此范围表示依赖性将在运行时由JDK或web-Server / Container提供。 |
3 | runtime 该范围表示编译时不需要依赖关系,但在执行期间需要。 |
4 | test 此范围表示依赖项仅适用于测试编译和执行阶段。 |
5 | system 此范围表示您必须提供系统路径。 |
6 | import 该范围仅在依赖类型为pom时使用。此范围表示应将指定的POM替换为该POM的<dependencyManagement>部分中的依赖项。 |
依赖管理
通常,我们在一个共同的项目下有一套项目。在这种情况下,我们可以创建一个具有所有通用依赖关系的通用pom,然后创建这个pom。下面的例子将帮助你理解这个概念。
以下是上述依赖图的细节 -
App-UI-WAR依赖于App-Core-lib和App-Data-lib。
Root是App-Core-lib和App-Data-lib的父代。
Root在其依赖项部分将Lib1,lib2,Lib3定义为依赖关系。
App-UI-WAR
<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.companyname.groupname</groupId> <artifactId>App-UI-WAR</artifactId> <version>1.0</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>com.companyname.groupname</groupId> <artifactId>App-Core-lib</artifactId> <version>1.0</version> </dependency> </dependencies> <dependencies> <dependency> <groupId>com.companyname.groupname</groupId> <artifactId>App-Data-lib</artifactId> <version>1.0</version> </dependency> </dependencies> </project> |
App-Core-lib
<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"> <parent> <artifactId>Root</artifactId> <groupId>com.companyname.groupname</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>App-Core-lib</artifactId> <version>1.0</version> <packaging>jar</packaging> </project> |
App-Data-lib
<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"> <parent> <artifactId>Root</artifactId> <groupId>com.companyname.groupname</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>App-Data-lib</artifactId> <version>1.0</version> <packaging>jar</packaging> </project> |
Root
<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.companyname.groupname</groupId> <artifactId>Root</artifactId> <version>1.0</version> <packaging>pom</packaging> <dependencies> <dependency> <groupId>com.companyname.groupname1</groupId> <artifactId>Lib1</artifactId> <version>1.0</version> </dependency> </dependencies> <dependencies> <dependency> <groupId>com.companyname.groupname2</groupId> <artifactId>Lib2</artifactId> <version>2.1</version> </dependency> </dependencies> <dependencies> <dependency> <groupId>com.companyname.groupname3</groupId> <artifactId>Lib3</artifactId> <version>1.1</version> </dependency> </dependencies> </project> |
现在,当我们构建App-UI-WAR项目时,Maven将通过遍历依赖关系图并构建应用程序来发现所有依赖关系。
从上面的例子中,我们可以学习以下关键概念 -
可以使用父pom的概念将常见的依赖关系放在一个地方。Root项目中列出了App-Data-lib和App-Core-lib项目的依赖关系(请参阅Root的packaging类型,即POM)。
在App-UI-WAR中不需要指定Lib1,lib2,Lib3作为依赖项。Maven使用Transitive Dependency Mechanism来管理这些细节。
16 部署自动化
在项目开发中,通常一个部署过程包含以下步骤 -
将所有正在进行的项目的代码签入SVN(版本控制系统)或源代码库并对其进行标记。
从SVN下载完整的源代码。
构建应用程序。
将构建输出存储到通用网络位置,即WAR或EAR文件。
从网络获取文件并将文件部署到生产站点。
使用日期和应用程序的更新版本号更新文档。
问题陈述
通常有多人参与上述部署过程。一个团队可以处理代码签入,其他人可以处理构建等。由于涉及人力和多团队环境,任何步骤都很可能会被遗漏。例如,旧版本可能无法在网络机器上替换,并且部署团队再次部署旧版本。
解决方案
结合以下内容自动执行部署流程 -
Maven,来构建和发布项目。
SubVersion,源代码库,管理源代码。
Remote Repository Manager(Jfrog / Nexus)管理项目二进制文件。
更新项目POM.xml
我们将使用Maven Release插件来创建一个自动发布过程。
例如:bus-core-api项目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>bus-core-api</groupId> <artifactId>bus-core-api</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <scm> <url>http://www.svn.com</url> <connection>scm:svn:http://localhost:8080/svn/jrepo/trunk/ Framework</connection> <developerConnection>scm:svn:${username}/${password}@localhost:8080: common_core_api:1101:code</developerConnection> </scm> <distributionManagement> <repository> <id>Core-API-Java-Release</id> <name>Release repository</name> <url>http://localhost:8081/nexus/content/repositories/ Core-Api-Release</url> </repository> </distributionManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-release-plugin</artifactId> <version>2.0-beta-9</version> <configuration> <useReleaseProfile>false</useReleaseProfile> <goals>deploy</goals> <scmCommentPrefix>[bus-core-api-release-checkin]-< /scmCommentPrefix> </configuration> </plugin> </plugins> </build> </project> |
在Pom.xml中,以下是我们使用的重要元素 -
Sr.No. | 元素和说明 |
1 | SCM 配置Maven将检出源代码的SVN位置。 |
2 | Repositories 构建WAR / EAR / JAR或任何其他工件的位置将在代码构建成功后存储。 |
3 | Plugin maven-release-plugin被配置为自动执行部署过程。 |
Maven发布插件
Maven使用maven-release-plugin执行以下有用的任务。
mvn release:clean |
它在最后的发布过程不成功的情况下清理工作区。
mvn release:rollback |
在最后的发布过程不成功的情况下,将修改完成回滚到工作区代码和配置。
mvn release:prepare |
执行多个操作,例如 -
检查是否有任何未提交的本地更改。
确保没有SNAPSHOT依赖关系。
更改应用程序的版本并从版本中删除SNAPSHOT以发布。
将pom文件更新为SVN。
运行测试用例。
提交修改后的POM文件。
在颠覆中标记代码
增加版本号并追加SNAPSHOT以备将来发布。
将修改后的POM文件提交给SVN。
mvn release:perform |
使用先前定义的标签检出代码并运行Maven deploy目标,将战争或构建的工件部署到存储库。
让我们打开命令控制台,进入C:\> MVN> bus-core-api目录并执行以下mvn命令。
>mvn release:prepare |
Maven将开始构建该项目。一旦构建成功,运行以下mvn命令。
>mvn release:perform |
一旦构建成功,您可以验证存储库中上传的JAR文件。
17 Web应用程序
本章将教您如何使用Maven管理基于Web的项目。在这里您将学习如何创建/构建/部署和运行Web应用程序。
创建Web应用程序
要创建一个简单的Java Web应用程序,我们将使用maven-archetype-webapp插件。因此,让我们打开命令控制台,转至C:\ MVN目录并执行以下mvn命令。
C:\MVN>mvn archetype:generate -DgroupId = com.companyname.automobile -DartifactId = trucks -DarchetypeArtifactId = maven-archetype-webapp -DinteractiveMode = false |
Maven将开始处理,并将创建完整的基于Web的Java应用程序项目结构,如下所示 -
[INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'archetype'. [INFO] ------------------------------------------------------------------- [INFO] Building Maven Default Project [INFO] task-segment: [archetype:generate] (aggregator-style) [INFO] ------------------------------------------------------------------- [INFO] Preparing archetype:generate [INFO] No goals needed for project - skipping [INFO] [archetype:generate {execution: default-cli}] [INFO] Generating project in Batch mode [INFO] -------------------------------------------------------------------- [INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-webapp:1.0 [INFO] --------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.companyname.automobile [INFO] Parameter: packageName, Value: com.companyname.automobile [INFO] Parameter: package, Value: com.companyname.automobile [INFO] Parameter: artifactId, Value: trucks [INFO] Parameter: basedir, Value: C:\MVN [INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: C:\MVN\trucks
[INFO] ------------------------------------------------------------------- [INFO] BUILD SUCCESSFUL [INFO] -------------------------------------------------------------------
[INFO] Total time: 16 seconds [INFO] Finished at: Tue Jul 17 11:00:00 IST 2012 [INFO] Final Memory: 20M/89M [INFO] ------------------------------------------------------------------- |
现在转到C:/ MVN目录。您将看到一个创建的java应用程序项目,名为trucks(如artifactId中所指定),如以下快照中所指定的。以下目录结构通常用于Web应用程序 -
Maven使用标准的目录布局。使用上面的例子,我们可以理解以下关键概念 -
Sr.No. | 文件夹结构和说明 |
1 | trucks 包含src文件夹和pom.xml。 |
2 | src/main/webapp 包含index.jsp和WEB-INF文件夹。 |
3 | src/main/webapp/WEB-INF 包含web.xml |
4 | src/main/resources 它包含图像/属性文件。 |
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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.automobile</groupId> <artifactId>trucks</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>trucks 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>trucks</finalName> </build> </project> |
如果您观察,您会发现Maven也创建了一个示例JSP源文件。
打开C:\> MVN> trucks> src> main> webapp>文件夹以使用以下代码查看index.jsp -
<html> <body> <h2>Hello World!</h2> </body> </html> |
构建Web应用程序
让我们打开命令控制台,转到C:\ MVN \ trucks目录并执行以下mvn命令。
C:\MVN\trucks>mvn clean package |
Maven将开始构建该项目。
[INFO] Scanning for projects... [INFO] ------------------------------------------------------------------- [INFO] Building trucks Maven Webapp [INFO] task-segment: [clean, package] [INFO] ------------------------------------------------------------------- [INFO] [clean:clean {execution: default-clean}] [INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources,i.e. build is platform dependent!
[INFO] Copying 0 resource [INFO] [compiler:compile {execution: default-compile}] [INFO] No sources to compile [INFO] [resources:testResources {execution: default-testResources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources,i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\MVN\trucks\src\test\resources [INFO] [compiler:testCompile {execution: default-testCompile}] [INFO] No sources to compile [INFO] [surefire:test {execution: default-test}] [INFO] No tests to run. [INFO] [war:war {execution: default-war}] [INFO] Packaging webapp [INFO] Assembling webapp[trucks] in [C:\MVN\trucks\target\trucks] [INFO] Processing war project [INFO] Copying webapp resources[C:\MVN\trucks\src\main\webapp] [INFO] Webapp assembled in[77 msecs] [INFO] Building war: C:\MVN\trucks\target\trucks.war [INFO] ------------------------------------------------------------------- [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------- [INFO] Total time: 3 seconds [INFO] Finished at: Tue Jul 17 11:22:45 IST 2012 [INFO] Final Memory: 11M/85M [INFO] ------------------------------------------------------------------- |
部署Web应用程序
现在将在C:\> MVN> trucks> target>文件夹中创建的trucks.war复制到您的webserver webapp目录并重新启动Web服务器。
测试Web应用程序
使用URL:http:// <server-name>:<port-number> /trucks/index.jsp运行Web应用程序。
验证输出。