admin 管理员组

文章数量: 1086019

阿帕奇 maven教程

阿帕奇 maven教程

Maven是Java™开发人员的出色构建工具,您也可以使用它来管理项目的生命周期。 作为生命周期管理工具,Maven跨阶段运行,而不是Ant风格的构建“任务”。 Maven处理项目生命周期的所有阶段,包括验证,代码生成,编译,测试,打包,集成测试,验证,安装,部署以及项目站点的创建和部署。

要了解Maven与传统构建工具之间的区别,请考虑构建JAR文件和EAR文件的过程。 使用Ant,您需要定义特定的任务来组装每个工件。 另一方面,Maven可以为您完成大部分工作:您只需告诉它项目是JAR还是EAR文件,然后指示它处理“打包”阶段即可。 Maven将找到所需的资源并构建文件。

您会发现许多入门指南,这些入门指南包括在本文的“ 相关主题”部分中列出的一些指南。 这里的五个技巧旨在帮助您了解接下来的内容:使用Maven管理应用程序生命周期时出现的编程方案。

1.可执行的JAR文件

关于本系列

所以您认为您了解Java编程吗? 事实是,大多数开发人员从头开始学习Java平台,仅学习足够的知识即可完成工作。 在这个正在进行的系列文章中,Java技术专家深入探讨了Java平台的核心功能,并提出了一些技巧和窍门,这些技巧和窍门甚至可以帮助您解决最棘手的编程挑战。

使用Maven构建JAR文件非常容易:只需将项目包装定义为“ jar”,然后执行包装生命周期阶段即可。 但是定义可执行的JAR文件更加棘手。 有效地执行此操作涉及以下步骤:

  1. 在您的JAR的MANIFEST.MF文件中定义一个main类,该main类定义了可执行类。 (MANIFEST.MF是打包应用程序时Maven生成的文件。)
  2. 查找项目依赖的所有库。
  3. 将那些库包括在MANIFEST.MF文件中,以便您的应用程序类可以找到它们。

您可以手动完成所有这些操作,也可以在两个Maven插件( maven-jar-pluginmaven-dependency-plugin的帮助下更有效地进行操作。

maven-jar-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文件的内容。 它包括三个元素:

  • addClassPath :将此元素设置为true可以告诉maven-jar-plugin将一个Class-Path元素添加到MANIFEST.MF文件,并在该Class-Path元素中包括所有依赖项
  • classpathPrefix :如果计划将所有依赖项与要构建的JAR包含在同一目录中,则可以忽略此元素; 否则,请使用classpathPrefix指定所有相关JAR文件的前缀。 在清单1中, classpathPrefix指定所有依赖项应位于相对于归档文件的“ lib ”文件夹中。
  • mainClass :使用此元素定义当用户使用java -jar命令执行JAR文件时要执行的类的名称。

Maven依赖插件

使用这三个元素配置MANIFEST.MF文件后,下一步是实际将所有依赖项复制到lib文件夹。 为此,您使用了maven-dependency-plugin ,如清单2所示:

清单2.使用maven-dependency-plugin将依赖项复制到lib
<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目录( project-home/target/lib )下的lib目录。

有了依赖关系并修改了MANIFEST.MF后,您可以使用简单的命令启动应用程序:

java -jar jarfilename.jar

2.自定义MANIFEST.MF

尽管maven-jar-plugin允许您修改MANIFEST.MF文件的公共部分,但有时您需要更自定义的MANIFEST.MF。 解决方案有两个:

  1. 在“模板” MANIFEST.MF文件中定义所有自定义配置。
  2. 配置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所示:

清单4.包括Premain-Class
<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>
Maven的3

Maven 2已成为最受欢迎和使用最广泛的开源Java生命周期管理工具之一。 Maven 3于2010年9月晋升为alpha 5,为Maven带来了一些期待已久的变化。 请参阅“ 相关主题”部分,以了解Maven 3的新增功能。

这是一个有趣的示例,因为它都定义了一个Premain-Class ,它允许JAR文件作为Java代理工作,并且具有mainClass ,使它可以作为可执行JAR文件运行。 在这个特定示例中,我使用了OpenAPM (我构建的代码跟踪工具)来定义将由Java代理和用户界面记录的代码跟踪,这将有助于对记录的跟踪进行分析。 简而言之,该示例显示了将显式清单文件与动态修改相结合的强大功能。

3.依赖树

Maven最有用的功能之一是它对依赖项管理的支持:您只需定义应用程序所依赖的库,然后Maven即可找到它们(在本地或中央存储库中),下载它们并使用它们来编译代码。 。

有时,您可能需要了解特定依赖项的来源-例如,如果要在构建中找到同一JAR文件的不同且不兼容的版本。 在这种情况下,您需要阻止将一个版本的JAR文件包含在您的构建中,但是首先您需要找到保存JAR的依赖项。

一旦您知道以下命令,查找依赖关系就变得异常容易:

mvn dependency:tree

dependency:tree参数显示所有直接依赖关系,然后显示所有子依赖关系(及其子依赖关系,依此类推)。 例如,清单5是我的一个依赖项所要求的客户端库的摘录:

清单5.一个Maven依赖树
[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-lgpleasymockclassextension库。 easymockclassextension库又需要cglib-nodep库和objenesis库。 如果我在使用objenesis遇到问题,例如1.2和1.3两个版本,则此依赖关系树将向我显示1.2工件是由easymockclassextension库间接导入的。

dependency:tree参数为我节省了许多调试损坏的构建的时间; 希望对您也一样。

4.针对不同环境的构建

大多数实质性项目至少具有一组核心环境,其中包括与开发,质量保证(QA),集成和生产相关的任务。 管理所有这些环境的挑战在于配置构建,该构建必须连接到正确的数据库,执行正确的脚本集并将所有正确的工件部署到每个环境。 使用Maven配置文件可让您执行所有这些操作,而不必分别为每个环境构建明确的说明。

关键在于将环境配置文件与面向任务的配置文件相结合。 每个环境概要文件都定义了其特定的位置,脚本和服务器。 因此,在我的pom.xml文件中,我将定义面向任务的构建,如清单6所示:

清单6.部署构建
<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>

此构建执行tomcat-deployer-plugin ,该tomcat-deployer-plugin配置为连接到特定的主机,端口以及特定的用户名和密码凭据。 所有这些信息都是使用变量定义的,例如${deploymentmanagerRestHost} 。 这些变量是在每个配置文件中按环境定义的,如清单7所示:

清单7.环境配置文件
<profiles><profile><id>dev</id><properties><deploymentManagerRestHost>10.50.50.52</deploymentManagerRestHost><deploymentManagerRestPort>58090</deploymentManagerRestPort><deploymentManagerRestUsername>myusername</deploymentManagerRestUsername><deploymentManagerRestPassword>mypassword</deploymentManagerRestPassword></properties></profile><profile><id>qa</id><properties><deploymentManagerRestHost>10.50.50.50</deploymentManagerRestHost><deploymentManagerRestPort>58090</deploymentManagerRestPort><deploymentManagerRestUsername>myotherusername</deploymentManagerRestUsername><deploymentManagerRestPassword>myotherpassword</deploymentManagerRestPassword></properties></profile>
</profiles>

部署Maven配置文件

在清单7的概要文件中,我定义了两个概要文件,并根据概要文件名称中的值激活了它们。 如果选择的概要文件是dev那么将使用开发部署信息。 如果选择的概要文件是qa ,那么将使用QA部署信息,依此类推。

这是部署到开发的命令:

mvn -Pdev clean install

–Pdev标志告诉Maven激活开发配置,而传递-Pqa将激活QA配置。

5.自定义Maven插件

Maven提供了数十种预建插件供您使用,但是在某些时候,您可能会发现自己需要自定义插件。 构建自定义Maven插件非常简单:

  1. 创建一个新项目,将POM包装设置为“ maven-plugin
  2. 包括对maven-plugin-plugin的调用,该调用定义了您公开的插件目标。
  3. 创建一个Maven插件“ mojo ”类(扩展AbstractMojo的类)。
  4. 注释该类以定义将作为配置参数公开的目标和变量。 注释@Mojo是必需的,它控制执行mojo的方式和时间。
  5. 实现execute()方法,当您的插件被调用时将被调用。

作为示例,清单8显示了用于部署Tomcat的自定义插件的相关部分:

清单8. TomcatDeployerMojo.java
package net.fpic.maven.plugins;import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;/*** Goal that deploys a web application to Tomcat*/
@Mojo(name = "deploy", defaultPhase = LifecyclePhase.INSTALL)
public class TomcatDeployerMojo extends AbstractMojo {/*** The host name or IP address of the deployment server*/@Parameter(alias = "host", property = "deploy.host", required = true)private String serverHost;/*** The port of the deployment server*/@Parameter(alias = "port", property = "deploy.port", defaultValue = "58020", required = true)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", property = "deploy.username")private String username;/*** The password for the specified username*/@Parameter(alias = "password", property = "deploy.password")private String password;/*** The name of the source artifact to deploy, such as target/pos.war*/@Parameter(alias = "artifactSource", property = "deploy.artifactSource", required = true)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", property = "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 fieldsif (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");}...}
}

在类级别, @Mojo批注值name指定此MOJO执行的目标,而lifecyclePhase指定目标执行的阶段。 除了映射到包含实际值的系统属性的表达式之外,每个公开的属性都有一个@Parameter批注,该批注指定将通过其执行参数的别名。 如果属性设置了required=true ,那么它是必需的。 如果它具有defaultValue ,那么如果未指定该值,则将使用该值。 在execute()方法中,可以调用getLog()来访问Maven记录器,该记录器将根据记录级别将指定的消息输出到标准输出设备。 如果该插件失败,则抛出MojoExecutionException将导致构建失败。

结论

您可以仅将Maven用于构建,但最好的Maven是项目生命周期管理工具。 本文介绍了五个鲜为人知的功能,这些功能可以帮助您更有效地使用Maven。 请参阅“ 相关主题”部分,以了解有关Maven的更多信息。


翻译自: .html

阿帕奇 maven教程

本文标签: 阿帕奇 maven教程