玩转Maven之使用入门
前言
说到Maven的入门使用,其实是特别简单的,如果只是说就是能使用,会使用Maven,也许只要短短的一两个小时就OK了,不需要去理解Maven的那些概念,而这篇文章就是要教会你会使用Maven,而整个系列则是要让你明白整个Maven。这篇文章就是如此,仅仅就是告诉你怎么用Maven,仅此而已,会用是学习整个系列的前提。
编写POM
就像composer的composer.json、Make的makefile文件一样,Maven项目的核心是pom.xml文件。POM(Project Object Model,项目对象模型)定义了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。
现在我们不借助任何其它命令和IDE,来创建一个Maven项目。
首先,编写pom.xml文件。还是按照老规矩,从一个Hello World项目进行演示。以下就是创建项目的POM文件。
<?xml version="1.0" encoding="UTF-8"?>
<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.jellythink.HelloWorld</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<name>hello-world</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
对于POM文件,现在细说一下。
代码的第一行是XML头,指定了该xml文档的版本和编码方式。紧接着是
project
元素,project
是所有pom.xml的根元素,它还声明了一些POM相关的命名空间及xsd元素;根元素下的第一个子元素
modelVersion
指定了当前POM模型的版本,对于Maven 2和Maven 3来说,它只能是4.0.0;接下来就是
groupId
、artifactId
和version
了,这三个是上述代码三个元素。这三个元素定义了一个项目的基本坐标,在Maven的世界里,所有的jar和war都是基于坐标进行区分的,会面的文章还会细说坐标;groupId
定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联,一般是使用组织或公司的域名;比如上面的groupId
是com.jellythink.HelloWorld
,其中com.jellythink
就是我的网站域名倒过来写的,而HelloWorld
则是整个项目的名称;artifactId
定义了当前Maven项目在组中唯一的ID,一般一个大项目组下面可能会包含多个子项目或子模块,而这个artifactId
就是子项目或者子模块的名称;version
指定了这个项目当前的版本,后面的文章还会细说Maven中版本的含义;name
元素声明了一个对于用户更为友好的项目名称,方便后期的管理;properties
指定了Maven的一些重要属性,后续还会重点说这个属性的一些配置。
创建完pom.xml文件后,接下来就是创建代码文件了。在Maven中,有这样的一个约定,项目主代码都位于src/main/java
目录,项目测试代码都位于src/test/java
目录;接下来我们先按照这个约定分别创建目录,然后在代码目录创建com/jellythink/HelloWorld/App.java
文件;在测试目录创建com/jellythink/HelloWorld/AppTest.java
文件。
还是老规矩,我们在App.java
中打印Hello World!,代码如下:
public class App {
public String sayHello() {
return "Hello World";
}
public static void main( String[] args ) {
System.out.println(new App().sayHello());
}
}
同理,对于AppTest.java
中编写以下单元测试代码:
public class AppTest {
@Test
public void testSayHello() {
App app = new App();
String result = app.sayHello();
assertEquals("Hello World", result);
}
}
在Java中,我们进行单元测试时,基本上都是使用的JUnit,要使用JUnit这个包,我们就需要引入这个依赖包,此时,我们就需要在pom.xml中添加以下依赖内容:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
代码中添加了dependencies
元素,该元素下可以包含多个dependency
元素以声明项目的依赖。前面也说过,groupId
、artifactId
和version
是任何一个Maven项目最基本的坐标,JUnit也不例外;scope
表示依赖范围,后续的文章还会细说这个依赖和测试相关的内容。
编译和测试
万事俱备,只欠东风。接下来我们编译和测试。
搞定代码后,使用Maven进行编译,在项目根目录下运行mvn clean compile
命令。执行输出如下图所示:
clean
告诉Maven清理输出目录target,compile
告诉Maven编译项目主代码。从输出中看到Maven首先执行了clean:clean
任务,删除target目录。默认情况下,Maven构建的所有输出都在target目录中;接着执行resources:resources
任务;最后执行compiler:compile
任务,将项目主代码编译至target/classes目录。
上面说到的clean:clean
、resources:resources
和compiler:compile
都对应了Maven的生命周期及插件,这个在后面还会有专题文章细说。
编译完成后,我们一般都会运行测试代码进行单元测试,虽然很多情况下,我们并没有这么做,但是我还是建议大家通过Maven做一些自动化的单元测试。
测试用例编写完毕之后就可以调用Maven执行测试,运行mvn clean test
命令,输出如下:
从输出可以看到,Maven依次执行了clean:clean
、resources:resources
、compiler:compile
、resources:testResources
、compiler:testCompile
和surefire:test
。现阶段,我们需要明白这是Maven的生命周期的一个特性,这个生命周期后续还会细说。
到此,编译和测试均通过了,接着我们进行应用打包和运行。
打包和运行
打包就是将我们编写的应用打成JAR包或者WAR包。在我们的HelloWorld示例程序POM中,并没有指定打包类型,Maven则默认打包成JAR包。我们执行mvn clean package
命令就可以完成打包。mvn clean package
命令的输出如下:
可以看到,Maven在打包之前会执行编译、测试等操作,最后通过jar:jar
任务负责打包。实际上就是jar插件的jar目标将项目主代码打包成一个名为hello-world-1.0-SNAPSHOT.jar的文件,这个最终生成的包会保存在target目录下,它是根据artifact-version.jar规则进行命名的;当然了,我们可以使用finalName属性来自定义该文件的名称。
到现在,我们得到了这个JAR包,如果别的项目要引用这个JAR包时,我们将这个JAR包复制到其它项目的classpath中就OK了。但是这样拷贝就违背了我们当初想要自动解决依赖的问题,所以如何才能让其它的Maven项目直接引用这个JAR包呢?我们需要执行mvn clean install
命令。
从输出可以看到,在打包之后,又执行了安装任务install:install
,最后将项目输出的JAR包安装到了Maven本地仓库中,我们可以在本地的仓库文件夹中能看到这个示例项目的pom和jar包。
到目前为止,通过这个示例项目体验了mvn clean compile
、mvn clean test
、mvn clean package
和mvn clean install
。执行test之前会先执行compile的,执行package之前会先执行test的,而类似地,install之前会执行package。我们可以在任何一个Maven项目中执行这些命令。
最后,不要忘了,我们生成的JAR包是有main方法的,也就是说这个JAR包是可以单独运行的;但是,由于带有main方法的类信息没有添加到manifest中,所以默认打包生成的jar是不能够直接运行的(使用jd-gui打开jar文件中的META-INF/MANIFEST.MF文件,将无法看到Main-Class一行)。为了生成可执行jar文件,需要借助Apache Maven Shade Plugin来完成,我们需要在pom.xml文件中以下插件配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.jellythink.HelloWorld.App</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
接下来,我们再执行mvn clean install
命令,待构建完成之后在target目录下可以看到hello-world-1.0-SNAPSHOT.jar和original-hello-world-1.0-SNAPSHOT.jar,前面的是带有Main-Class信息的可运行jar,后者是原始的jar。我们执行以下命令:
java -jar hello-world-1.0-SNAPSHOT.jar
就可以正常执行。
使用Archetype生成项目骨架
上面非常详细的总结了如何全手动的创建一个Maven工程。通过上面的总结,我们大体可以总结以下几步:
在项目根目录创建pom.xml文件;
创建
src/main/java
目录,并在该目录开发项目主代码;创建
src/test/java
目录,并在该目录开发项目测试代码;
上面的三步我们成为Maven项目的骨架,也就是现在常说的“脚手架”。如果我们每创建一个Maven项目都需要把上面的步骤执行一次,确实很麻烦,那怎么办?程序就是解放人工的,让人来偷懒的。所以,在Maven中,我们可以通过Archetype生成项目骨架,将上面的步骤流程化。比如,现在我们要创建一个Maven项目,我们只需要输入以下命令就OK了。
mvn archetype:generate
执行这个命令后,后看到很多输出,有很多可用的Archetype供我们选择,每一个Archetype前面都会对应有一个编号,我们根据我们的需要,选择我们对应的骨架来创建项目就好了。然后再按照提示,输出新项目的groupId、artifactId、version和包名package,一个Maven项目就创建成功了。
我们在运行mvn archetype:generate
时,实际上是在运行maven-archetype-plugin
插件。
总结
到此,这篇关于Maven的初级入门文章就到此总结完毕,这篇文章的知识点比较多,而且还很杂,如果看的有点不是很懂,也没有关系,后续的文章都会对这些你不懂的地方,你不熟悉的地方在进行深入的剖析和总结。当然了,也希望大家能通过这篇文章对Maven的使用有一个整体的认识,至少没有后续的文章,通过这篇文章,你也应该知道怎么使用Maven了,不是吗?
这一夜,深深的自责中......
往期精彩回顾
1、《玩转Maven之安装与配置》
书籍推荐
人生是个圆,有的人走了一辈子也没有走出命运画出的圆圈,其实,圆上的每一个点都有一条腾飞的切线。
玩代码、玩技术
长按识别二维码,关注“果冻想”