6
这又是一个系列,一个要把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;
  • 接下来就是groupIdartifactIdversion了,这三个是上述代码三个元素。这三个元素定义了一个项目的基本坐标,在Maven的世界里,所有的jar和war都是基于坐标进行区分的,会面的文章还会细说坐标;
  • groupId定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联,一般是使用组织或公司的域名;比如上面的groupIdcom.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元素以声明项目的依赖。前面也说过,groupIdartifactIdversion是任何一个Maven项目最基本的坐标,JUnit也不例外;scope表示依赖范围,后续的文章还会细说这个依赖和测试相关的内容。

编译和测试

万事俱备,只欠东风。接下来我们编译和测试。

搞定代码后,使用Maven进行编译,在项目根目录下运行mvn clean compile命令。执行输出如下图所示:

mvn clean compile

clean告诉Maven清理输出目录target,compile告诉Maven编译项目主代码。从输出中看到Maven首先执行了clean:clean任务,删除target目录。默认情况下,Maven构建的所有输出都在target目录中;接着执行resources:resources任务;最后执行compiler:compile任务,将项目主代码编译至target/classes目录。

上面说到的clean:cleanresources:resourcescompiler:compile都对应了Maven的生命周期及插件,这个在后面还会有专题文章细说。

编译完成后,我们一般都会运行测试代码进行单元测试,虽然很多情况下,我们并没有这么做,但是我还是建议大家通过Maven做一些自动化的单元测试。

测试用例编写完毕之后就可以调用Maven执行测试,运行mvn clean test命令,输出如下:

mvn clean test

从输出可以看到,Maven依次执行了clean:cleanresources:resourcescompiler:compileresources:testResourcescompiler:testCompilesurefire:test。现阶段,我们需要明白这是Maven的生命周期的一个特性,这个生命周期后续还会细说。

到此,编译和测试均通过了,接着我们进行应用打包和运行。

打包和运行

打包就是将我们编写的应用打成JAR包或者WAR包。在我们的HelloWorld示例程序POM中,并没有指定打包类型,Maven则默认打包成JAR包。我们执行mvn clean package命令就可以完成打包。mvn clean package命令的输出如下:

mvnCleanPackage.png

可以看到,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命令。

mvnCleanInstall.png

从输出可以看到,在打包之后,又执行了安装任务install:install,最后将项目输出的JAR包安装到了Maven本地仓库中,我们可以在本地的仓库文件夹中能看到这个示例项目的pom和jar包。

到目前为止,通过这个示例项目体验了mvn clean compilemvn clean testmvn clean packagemvn 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了,不是吗?

这一夜,深深的自责中......

果冻想,认真玩技术的地方。

2019年4月1日,于内蒙古呼和浩特。


微信扫码关注公众号


果冻想
430 声望32 粉丝