Maven 是为 Java™ 开发人员提供的一个极为优秀的构建工具,您也可以使用它来管理您的项目生命周期。作为一个生命周期管理工具,Maven 是基于阶段操作的,而不像 Ant 是基于 “任务” 构建的。Maven 完成项目生命周期的所有阶段,包括验证、代码生成、编译、测试、打包、集成测试、安装、部署、以及项目网站创建和部署。
为了更好地理解 Maven 和传统构建工具的不同,我们来看看构建一个 JAR 文件和一个 EAR 文件的过程。使用 Ant,您可能需要定义专有任务来组装每个工件。另一方面,Maven 可以为您完成大部分工作:您只需要告诉它是一个 JAR 文件还是一个 EAR 文件,然后指示它来完成 “打包” 过程。Maven 将会找到所需的资源,然后构建文件。
在本文的 参考资料 部分,您将发现大量介绍 Maven 的入门教程。本文的 5 个技巧目的是帮助您解决即将出现的一些问题:使用 Maven 管理您的应用程序的生命周期时,将会出现的编程场景。
使用 Maven 构建一个 JAR 文件比较容易:只要定义项目包装为 “jar”,然后执行包装生命周期阶段即可。但是定义一个可执行 JAR 文件却比较麻烦。采取以下步骤可以更高效:
- 在您定义可执行类的 JAR 的 MANIFEST.MF 文件中定义一个
main
类。(MANIFEST.MF 是包装您的应用程序时 Maven 生成的。) - 找到您项目依赖的所有库。
- 在您的 MANIFEST.MF 文件中包含那些库,便于您的应用程序找到它们。
您可以手工进行这些操作,或者要想更高效,您可以使用两个 Maven 插件帮助您完成:maven-jar-plugin
和 maven-dependency-plugin
。
maven-jar-plugin
可以做很多事情,但在这里,我们只对使用它来修改默认 MANIFEST.MF 文件的内容感兴趣。在您的 POM 文件的插件部分添加清单 1 所示代码:
清单 1. 使用 maven-jar-plugin 修改 MANIFEST.MF
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.mypackage.MyClass</mainClass> </manifest> </archive> </configuration> </plugin> |
所有 Maven 插件通过一个 <configuration>
元素公布了其配置,在本例中,maven-jar-plugin
修改它的 archive
属性,特别是存档文件的 manifest
属性,它控制 MANIFEST.MF 文件的内容。包括 3 个元素:
-
addClassPath
:将该元素设置为 true 告知maven-jar-plugin
添加一个Class-Path
元素到 MANIFEST.MF 文件,以及在Class-Path
元素中包括所有依赖项。 -
classpathPrefix
:如果您计划在同一目录下包含有您的所有依赖项,作为您将构建的 JAR,那么您可以忽略它;否则使用classpathPrefix
来指定所有依赖 JAR 文件的前缀。在清单 1 中,classpathPrefix
指出,相对存档文件,所有的依赖项应该位于 “lib
” 文件夹。 -
mainClass
:当用户使用lib
命令执行 JAR 文件时,使用该元素定义将要执行的类名。
当您使用这 3 个元素配置好了 MANIFEST.MF 文件之后,下一步是将所有的依赖项复制到 lib
文件夹。为此,使用 maven-dependency-plugin
,如清单 2 所示:
清单 2. 使用 maven-dependency-plugin 将依赖项复制到库
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy</id> <phase>install</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory> ${project.build.directory}/lib </outputDirectory> </configuration> </execution> </executions> </plugin> |
maven-dependency-plugin
有一个 copy-dependencies
,目标是将您的依赖项复制到您所选择的目录。本例中,我将依赖项复制到 build
目录下的 lib
目录(project-home/target/lib
)。
将您的依赖项和修改的 MANIFEST.MF 放在适当的位置后,您就可以用一个简单的命令启动应用程序:
java -jar jarfilename.jar |
虽然 maven-jar-plugin
允许您修改 MANIFEST.MF
文件的共有部分,但有时候您需要一个更个性化的 MANIFEST.MF。解决方案是双重的:
- 在一个 “模板” MANIFEST.MF 文件中定义您的所有定制配置。
- 配置
maven-jar-plugin
来使用您的 MANIFEST.MF 文件,然后使用一些 Maven 配置增强。
例如,考虑一个包含 Java 代理的 JAR 文件。要运行一个 Java 代理,需要定义 Premain-Class
和设置许可。清单 3 展示了这样一个 MANIFEST.MF 文件的内容:
清单 3. 在一个定制的 MANIFEST.MF 文件中定义 Premain-Class
Manifest-Version: 1.0 Premain-Class: com.geekcap.openapm.jvm.agent.Agent Can-Redefine-Classes: true Can-Retransform-Classes: true Can-Set-Native-Method-Prefix: true |
在 清单 3 中,我已指定 Premain-Class
- com.geekcap.openapm.jvm.agent.Agent
被授权许可来对类进行重定义和再转换。接下来,我更新 maven-jar-plugin
代码来包含 MANIFEST.MF 文件。如清单 4 所示:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifestFile> src/main/resources/META-INF/MANIFEST.MF </manifestFile> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass> com.geekcap.openapm.ui.PerformanceAnalyzer </mainClass> </manifest> </archive> </configuration> </plugin> |
这是一个很有趣的示例,因为它既定义了一个 Premain-Class
— 允许 JAR 文件作为一个 Java 代理运行,也有一个 mainClass
— 允许它作为一个可执行的 JAR 文件运行。在这个特殊的例子中,我使用OpenAPM
(我已构建的一个代码跟踪工具)来定义将被 Java 代理和一个用户界面记录的代码跟踪。简而言之,这个示例展示一个显式清单文件与动态修改相结合的力量。
Maven 一个最有用的功能是它支持依赖项管理:您只需要定义您应用程序依赖的库,Maven 找到它们、下载它们、然后使用它们编译您的代码。
必要时,您需要知道具体依赖项的来源 — 这样您就可以找到同一个 JAR 文件的不同版本的区别和矛盾。这种情况下,您将需要防止将一个版本的 JAR 文件包含在您的构建中,但是首先您需要定位保存 JAR 的依赖项。
一旦您知道下列命令,那么定位依赖项往往是相当容易的:
mvn dependency:tree |
dependency:tree
参数显示您的所有直接依赖项,然后显示所有子依赖项(以及它们的子依赖项,等等)。例如,清单 5 节选自我的一个依赖项所需要的客户端库:
[INFO] ------------------------------------------------------------------------ [INFO] Building Client library for communicating with the LDE [INFO] task-segment: [dependency:tree] [INFO] ------------------------------------------------------------------------ [INFO] [dependency:tree {execution: default-cli}] [INFO] com.lmt.pos:sis-client:jar:2.1.14 [INFO] +- org.codehaus.woodstox:woodstox-core-lgpl:jar:4.0.7:compile [INFO] | \- org.codehaus.woodstox:stax2-api:jar:3.0.1:compile [INFO] +- org.easymock:easymockclassextension:jar:2.5.2:test [INFO] | +- cglib:cglib-nodep:jar:2.2:test [INFO] | \- org.objenesis:objenesis:jar:1.2:test |
在 清单 5 中您可以看到 sis-client
项目需要 woodstox-core-lgpl
和 easymockclassextension
库。easymockclassextension
库反过来需要 cglib-nodep
库和 objenesis
库。如果我的 objenesis
出了问题,比如出现两个版本,1.2 和 1.3,那么这个依赖项树可能会向我显示,1.2 工件是直接由 easymockclassextension
库导入的。
dependency:tree
参数为我节省了很多调试时间,我希望对您也同样有帮助。
多数重大项目至少有一个核心环境,由开发相关的任务、质量保证(QA)、集成和生产组成。管理所有这些环境的挑战是配置您的构建,这必须连接到正确的数据库中,执行正确的脚本集、并为每个环境部署正确的工件。使用 Maven 配置文件让您完成这些任务,而无需为每个环境分别建立明确指令。
关键在于环境配置文件和面向任务的配置文件的合并。每个环境配置文件定义其特定的位置、脚本和服务器。因此,在我的 pox.xml 文件中,我将定义面向任务的配置文件 “deploywar
”,如清单 6 所示:
<profiles> <profile> <id>deploywar</id> <build> <plugins> <plugin> <groupId>net.fpic</groupId> <artifactId>tomcat-deployer-plugin</artifactId> <version>1.0-SNAPSHOT</version> <executions> <execution> <id>pos</id> <phase>install</phase> <goals> <goal>deploy</goal> </goals> <configuration> <host>${deploymentManagerRestHost}</host> <port>${deploymentManagerRestPort}</port> <username>${deploymentManagerRestUsername}</username> <password>${deploymentManagerRestPassword}</password> <artifactSource> address/target/addressservice.war </artifactSource> </configuration> </execution> </executions> </plugin> </plugins> </build> </profile> </profiles> |
这个配置文件(通过 ID “deploywar
” 区别)执行 tomcat-deployer-plugin
,被配置来连接一个特定主机和端口,以及指定用户名和密码证书。所有这些信息使用变量来定义,比如 ${deploymentmanagerRestHost}
。这些变量在我的 profiles.xml 文件中定义,如清单 7 所示:
<!-- Defines the development deployment information --> <profile> <id>dev</id> <activation> <property> <name>env</name> <value>dev</value> </property> </activation> <properties> <deploymentManagerRestHost>10.50.50.52</deploymentManagerRestHost> <deploymentManagerRestPort>58090</deploymentManagerRestPort> <deploymentManagerRestUsername>myusername</deploymentManagerRestUsername> <deploymentManagerRestPassword>mypassword</deploymentManagerRestPassword> </properties> </profile> <!-- Defines the QA deployment information --> <profile> <id>qa</id> <activation> <property> <name>env</name> <value>qa</value> </property> </activation> <properties> <deploymentManagerRestHost>10.50.50.50</deploymentManagerRestHost> <deploymentManagerRestPort>58090</deploymentManagerRestPort> <deploymentManagerRestUsername> myotherusername </deploymentManagerRestUsername> <deploymentManagerRestPassword> myotherpassword </deploymentManagerRestPassword> </properties> </profile> |
在 清单 7 的 profiles.xml 文件中,我定义了两个配置文件,并根据 env
(环境)属性的值激活它们。如果 env
属性被设置为 dev
,则使用开发部署信息。如果 env
属性被设置为 qa
,那么将使用 QA 部署信息,等等。
这是部署文件的命令:
mvn -Pdeploywar -Denv=dev clean install |
-Pdeploywar
标记通知要明确包含 deploywar
配置文件。-Denv=dev
语句创建一个名为 env
的系统属性,并将其值设为 dev
,这激活了开发配置。传递 -Denv=qa
将激活 QA 配置。
Maven 有十几个预构建插件供您使用,但是有时候您只想找到自己需要的插件,构建一个定制的 Maven 插件比较容易:
- 用 POM packaging 创建一个新项目,设置为 “
maven-plugin
”。 - 包括一个
maven-plugin-plugin
调用,可以定义您的公布插件目标。 - 创建一个 Maven 插件 “
mojo
” 类 (一个扩展AbstractMojo
的类)。 - 为类的 Javadoc 做注释来定义目标,并为每个将被作为配置参数公布的变量做注解。
- 实现一个
execute()
方法,该方法在调用您的插件是将被调用。
例如,清单 8 显示了一个定制插件(为了部署 Tomcat)的相关部分:
package net.fpic.maven.plugins; import java.io.File; import java.util.StringTokenizer; import net.fpic.tomcatservice64.TomcatDeploymentServerClient; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import com.javasrc.server.embedded.CommandRequest; import com.javasrc.server.embedded.CommandResponse; import com.javasrc.server.embedded.credentials.Credentials; import com.javasrc.server.embedded.credentials.UsernamePasswordCredentials; import com.javasrc.util.FileUtils; /** * Goal that deploys a web application to Tomcat * * @goal deploy * @phase install */ public class TomcatDeployerMojo extends AbstractMojo { /** * The host name or IP address of the deployment server * * @parameter alias="host" expression="${deploy.host}" @required */ private String serverHost; /** * The port of the deployment server * * @parameter alias="port" expression="${deploy.port}" default-value="58020" */ private String serverPort; /** * The username to connect to the deployment manager (if omitted then the plugin * attempts to deploy the application to the server without credentials) * * @parameter alias="username" expression="${deploy.username}" */ private String username; /** * The password for the specified username * * @parameter alias="password" expression="${deploy.password}" */ private String password; /** * The name of the source artifact to deploy, such as target/pos.war * * @parameter alias="artifactSource" expression=${deploy.artifactSource}" * @required */ private String artifactSource; /** * The destination name of the artifact to deploy, such as ROOT.war. * If not present then the * artifact source name is used (without pathing information) * * @parameter alias="artifactDestination" * expression=${deploy.artifactDestination}" */ private String artifactDestination; public void execute() throws MojoExecutionException { getLog().info( "Server Host: " + serverHost + ", Server Port: " + serverPort + ", Artifact Source: " + artifactSource + ", Artifact Destination: " + artifactDestination ); // Validate our fields if( serverHost == null ) { throw new MojoExecutionException( "No deployment host specified, deployment is not possible" ); } if( artifactSource == null ) { throw new MojoExecutionException( "No source artifact is specified, deployment is not possible" ); } ... } } |
在这个类的头部,@goal
注释指定 MOJO 执行的目标,而 @phase
指出目标执行的阶段。除了一个映射到一个有真实值的系统属性的表达式之外,每个公布的属性有一个 @phase
注释,通过将被执行的参数指定别名。如果属性有一个 @required
注释,那么它是必须的。如果它有一个 default-value
,那么如果没有指定的话,将使用这个值。在 execute()
方法中,您可以调用 getLog()
来访问 Maven 记录器,根据记录级别,它将输出具体消息到标准输出设备。如果插件发生故障,抛出一个MojoExecutionException
将导致构建失败。
您可以使用 Maven 只进行构建,但是最好的 Maven 是一个项目生命周期管理工具。本文介绍了 5 个大家很少了解的特性,可以帮助您更高效地使用 Maven。在 参考资料 部分获取 Maven 的更多信息。
下一篇 5 件事系列 文章是关于使用 Swing 构建漂亮的用户界面的 5个技巧,敬请关注。
学习
- “ 关于...您不知道的 5 件事”:了解 Java 平台中您还有多少不知道的知识,这个系列专门将烦琐的 Java 技术变成非常有用的编程技巧。
- “ Apache Maven 2 简介”(Sing Li,developerWorks,2006 年 12 月):熟悉使用 Maven 2 构建项目所需要的基本技能,从该 developerWorks 教程开始。
- “Managing Java Build Lifecycles with Maven”(Steven Haines,InformIT.com,2009 年 7 月):该教程介绍了 Maven 的基础知识、基础架构、以及如何使用它来管理您的 Java 项目的构建生命周期。
-
Maven: The Complete Reference, Edition 0.7(Tim O'Brien,et al.;Sonatype 2010):这个免费在线图书是学习 Maven 的一个极佳资料。包括即将使用的 Maven 3 的技巧。发行人 SonaType 是一个软件零售商,开发过一个最著名的 Maven 库 Nexus。
-
Maven 3 版本说明:了解 Maven 3 中的变化,包括可用性和性能方面的改进。
-
developerWorks Java 技术专区:这里有数百篇关于 Java 编程每个方面的文章。
获得产品和技术
-
Maven 主页:下载 Maven 并从 Apache Software Foundation 了解关于它的更多信息。
讨论
- 加入 My developerWorks 中文社区。与其他 developerWorks 用户交流,同时浏览开发人员推动的博客、论坛、群组和 Wiki。
相关推荐
apache-maven-3.6.3-bin。apache-maven-3.6.3-bin。apache-maven-3.6.3-bin。apache-maven-3.6.3-bin。apache-maven-3.6.3-bin。apache-maven-3.6.3-bin。apache-maven-3.6.3-bin。apache-maven-3.6.3-bin。apache-...
apache maven 3.x.x所有Linux, Windows版本下载的百度网盘链接。 apache-maven-3.0.4-bin.tar.gz apache-maven-3.0.4-bin.zip apache-maven-3.0.5-bin.tar.gz apache-maven-3.0.5-bin.zip apache-maven-3.1.0-bin....
apache-maven-3.8.6-bin.zip apache-maven-3.8.6-bin.zip apache-maven-3.8.6-bin.zip apache-maven-3.8.6-bin.zip apache-maven-3.8.6-bin.zip apache-maven-3.8.6-bin.zip apache-maven-3.8.6-bin.zip apache-...
apache-maven-3.6.1.zip分享给需要的同学 apache-maven-3.6.1.zip分享给需要的同学 apache-maven-3.6.1.zip分享给需要的同学 apache-maven-3.6.1.zip分享给需要的同学 apache-maven-3.6.1.zip分享给需要的同学apache...
Apache Maven 是一个强大的项目管理和构建工具,主要用于Java项目。它基于项目对象模型(Project Object Model,POM)的概念,能够管理项目的构建、报告和文档。Maven 3.6.0是该工具的一个稳定版本,提供了许多改进...
Apache Maven 是一个强大的项目管理和构建工具,主要用于Java应用程序的开发。它通过定义项目的构建过程、依赖关系和项目信息,使得开发人员能够以一种标准化的方式管理项目。Maven 的核心概念是基于项目对象模型...
Apache Maven Cookbook is for those who want to learn how Apache Maven can be used for build automation. It is also meant for those familiar with Apache Maven, but want to understand the finer nuances ...
Apache Maven是一个流行的项目管理工具,主要用于Java项目,帮助开发者自动化构建、文档创建和报告项目信息。 如果你想安装和使用Apache Maven 3.8.3,你需要首先下载这个zip文件,然后解压到适当的目录。一旦解压...
Apache Maven 是一个强大的项目管理和构建工具,主要用于Java应用程序的开发。它基于项目对象模型(Project Object Model,POM)的概念,使得项目的构建、依赖管理、文档生成、代码质量检查等任务变得简单。Apache ...
Apache Maven 是一个强大的Java项目管理工具,它极大地简化了构建、依赖管理和项目文档的生成过程。Maven 3.6.0是该工具的一个稳定版本,提供了多项改进和新特性,旨在提高开发效率和增强项目的可维护性。 Maven的...
Apache Maven 是一个强大的项目管理和构建工具,主要用于Java项目。它基于项目对象模型(Project Object Model,POM)的概念,能够管理项目的构建、报告和依赖关系。Maven 的核心理念是通过标准化的构建生命周期和...
Apache Maven。什么是Maven?简而言之,Maven是我们可以用来构建和管理基于Java的项目的工具。与较旧的构建工具(例如Ant)(同样也是Apache项目)相比,Maven为开发人员提供了一种标准的方法来构建项目,对项目所...
Apache Maven 是一个强大的Java项目管理和综合工具,它简化了构建过程,通过标准化项目结构和自动化构建生命周期。在本文中,我们将深入探讨Maven的核心概念、安装步骤以及如何在实际项目中使用它。 **Maven核心...
apache-maven-3.8.8.zip压缩包内容: apache-maven-3.8.8-bin.tar.gz apache-maven-3.8.8-bin.zip apache-maven-3.8.8-src.tar.gz apache-maven-3.8.8-src.zip
总的来说,Apache Maven 3.9.6 是Java开发中不可或缺的工具,它简化了项目构建过程,提高了团队协作的效率,同时也为持续集成和自动化测试提供了坚实的基础。无论是初学者还是经验丰富的开发者,都能从Maven的强大...
Apache Maven 是一个强大的项目管理和构建工具,主要用于Java应用程序的开发。Maven 使用一种标准化的项目对象模型(Project Object Model,POM),使得构建过程、依赖管理、报告生成以及项目的配置变得更加简单。...
在您提供的"apache-maven-3.6.1 安装包"中,我们主要关注的是Maven的3.6.1版本。这个版本包含了Maven的核心组件、插件和文档,用于在本地计算机上安装和使用Maven。下面将详细解释Maven的相关知识点: 1. **Maven...
4. `LICENSE` 和 `NOTICE` 文件:提供了关于Apache Maven的许可和版权信息。 5. `README.txt` 或类似的文件:可能包含了安装和使用Maven的简要指南。 在实际开发中,使用Maven有以下几个关键优点: - **依赖管理**...
Apache Maven (apache-maven-3.8.4-bin.zip)是一个软件项目管理和理解工具。基于项目对象模型 (POM) 的概念,Maven 可以从一条中央信息中管理项目的构建、报告和文档。
Apache Maven是Java开发领域广泛应用的一款项目管理工具,它基于项目对象模型(Project Object Model, POM)的概念,能够自动化构建、依赖管理和项目信息管理。在本文中,我们将深入探讨Maven 3.9.6这一版本,以及它...