你居然没用 Maven 构建项目?

一年前,当我和小伙伴小龙一块儿作一个外包项目的时候,受到了严重的鄙视。我那时候还不知道 Maven,因此搭建项目用的仍是最原始的方式,小龙不得已在导入项目的时候花了很长时间去下载项目依赖的开源类库。前端

出于对个人尊重,小龙没有破口大骂,而是很是委婉地说了一句:“二哥,你好歹也有必定的知名度了,居然没用 Maven 构建项目,真让我大开眼界啊。”java

做为一名富有上进心的程序员,不能忍啊。借此机会,有必要隆重地向你们介绍一下 Maven 了。程序员

0一、Maven 是什么?

无论英文功底好很差,先看看官网给出的介绍语吧:web

Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information.spring

大体的意思就是说,Apache Maven 是一个项目管理和自动化构建工具,基于项目对象模型(POM)的概念,能够管理项目的构建、报告以及文档。做为 Apache 组织中的一个颇为成功的开源项目,Maven 主要服务于基于 Java 的项目构建、依赖管理和项目信息管理apache

Maven 采用了约定优先配置的原则,这些原则以下表所示:app

目录 目的
${basedir} 存放 pom.xml 和全部的子目录
${basedir}/src/main/java 存放 Java 源代码
${basedir}/src/main/resources 存放项目的资源文件,好比说 log4j.properties
${basedir}/src/test/java 存放测试类
${basedir}/src/test/resources 存放测试用的资源
${basedir}/src/main/webapp 存放 Web 前端文件
${basedir}/target 项目打包后的输出目录
${basedir}/target/classes 项目编译后输出目录
~/.m2/repository 默认的 Maven 仓库目录(~表示用户目录)

使用约定优先配置带来的最大好处就是项目的目录结构图很是的统一,不一样的开发者在开发一个 Maven 项目的时候,文件存放位置几乎没有差异,省去了不少没必要要的麻烦,有利于促进项目团队的标准化。webapp

咱们这个年代很是崇尚开源精神,几乎全部的 Java 项目都会借用一些第三方的开源类库,这些类库能够经过依赖的方式引入到项目中来。但随着依赖的增多,版本冲突、依赖臃肿的问题就会接踵而来。手工解决这些问题是十分枯燥的,幸运的是 Maven 提供了一个优秀的解决方案,它经过一个三维的坐标(<groupId><artifactId><version>)来准确地定位每个开源类库。maven

另外,我认为 Maven 特别优秀的一点是,它把项目依赖的全部开源类库都从远程中央仓库下载到了指定的本地仓库中,也就是说,这些开源类库能够在多个项目之间共用,无需重复下载——假如我用 Maven 构建项目的话,小龙就不用下载那么多开源类库了,他的本地仓库中可能已经有了——我也就不会被鄙视了。ide

0二、配置 Maven 环境

1)安装 Maven 以前,先确保电脑上已经安装了 JDK。

2)去 Maven 官网下载想要的版本并解压,下载地址为:

maven.apache.org/download.cg…

3)设置环境变量,主要是 MAVEN_HOME 和 Path。

4)打开命令行,输入 mvn -v 验证 Maven 是否配置成功。

5)Maven 的 conf 目录下包含了一个很是重要的文件 settings.xml,通常状况下,我倾向于将该文件复制到 ~/.m2/ 目录下——建议你也这么作。

打开该文件,在 <mirrors></mirrors> 节点下添加阿里云的镜像地址(参照下面的代码)。为何要这么作呢?由于 Maven 默认的仓库在不翻强的状况下很难访问到。

<mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>        
</mirror>
复制代码

这里须要注意的是,<mirrorOf> 的值有下面四种方式:

  • <mirrorOf>*<mirrorOf>:匹配全部远程仓库,也就是说任何对于中央仓库的请求都会转至该镜像。
  • <mirrorOf>external:*<mirrorOf>:匹配全部不在本机上的远程仓库。
  • <mirrorOf>repo1,repo2<mirrorOf>:匹配仓库 repo1 和 repo2,使用逗号分隔多个远程仓库。
  • <mirrorOf>*,!repo<mirrorOf>:匹配全部远程仓库,repo 除外,使用感叹号将仓库从匹配中排除。

6)在 Eclipse 下依次选择菜单 Window → Show View → Other → Maven → Maven Workspace Build,查看镜像是否配置成功(我习惯了使用 Eclipse,因此请见谅,不过无论使用哪一种集成开发环境,思路和步骤都大差不差)。

0三、快速建立 Maven 项目

为了尽快步入重点,这一小节我会有意的拈轻怕重,不必的步骤会略过。

1)在 Eclipse 中新建项目的时候选择 Maven Project。

2)在接下来选择项目类型的时候,选择 maven-archetype-quickstart,以下图所示。

3)而后指定项目参数的时候填写 group id 和 artifact id。

4)项目建立成功后的目录结构图以下图所示。

Maven 3 默认使用的依然是 JDK 1.5,不过咱们能够为其配置更高版本的 JDK,后面会聊到。

0四、详细分析 pom.xml

毫无疑问,Maven 项目的灵魂只有一个,那就是 pom.xml 文件,因此接下来我会详细地对其进行分析。

1)项目基本信息

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.cmower</groupId>
  <artifactId>test</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>test</name>

</project>
复制代码

①、<project> 是 pom.xml 的根元素,声明了相关的命名空间。

②、<modelVersion> 指定了当前项目对象模型(POM)的版本,对于 Maven 3.x 来讲,该值只能是 4.0.0。

③、<groupId> 定义了项目的组名,这个组每每和项目所在的组织或公司关联。

④、<artifactId> 定义了当前 Maven 项目在组中惟一的 ID。

⑤、<version> 定义了项目的版本号,SNAPSHOT 为快照的意思,也就是说该项目还处于开发阶段。

⑥、<packaging> 定义了项目的打包类型,可选值有 war、jar 等。

⑦、<name> 定义了项目的名称。

2)变量配置信息

pom.xml 文件的第二部分一般用来配置一些变量信息。

<properties>
    <spring.version>5.1.5.RELEASE</spring.version>
</properties>
复制代码

有了变量的配置信息后,能够经过 ${spring.version} 的形式来调用这些配置项。这样作的好处显而易见,当依赖项的版本升级的时候,能够直接修改变量值便可。

3)依赖管理

阿里云的 Maven 仓库下有各类各样的第三方类库,换句话说就是,只有你想不到的,没有你找不到的。大多数 Maven 项目的依赖项列表都会很长很长,为了便于说明,下面我只列出某些具备特点的。

<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>3.8.1</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-core</artifactId>
		<version>${spring.version}</version>
		<exclusions>
			<exclusion>
				<groupId>commons-logging</groupId>
				<artifactId>commons-logging</artifactId>
			</exclusion>
		</exclusions>
	</dependency>
	<dependency>
		<groupId>commons-logging</groupId>
		<artifactId>commons-logging</artifactId>
		<version>1.1.1</version>
	</dependency>
</dependencies>
复制代码

①、上文中曾提到,<groupId><artifactId><version> 合起来能够准确地定位一个依赖项。那怎么找到想要的依赖项呢?

第一步,进入 MavenRepository 网站,地址以下:

mvnrepository.com

而后在搜索框中输入第三方类库的关键字,好比说「spring-core」,点击「search」按钮,能够查看到该类库的连接导航。

第二步,点击连接进入到「spring-core」的主页,能够看到全部版本的「spring-core」,选择一个使用率最高的。使用率高在必定程度上代表这个版本的类库最稳定,它已经获得了广大程序员的承认。

第三步,进入该版本的主页,只须要左键轻轻地在 「Maven」选项卡内点一下,就已经把该类库的 Maven 依赖信息复制到粘贴板了(不须要「Ctrl+C」,很是的人性化),以下图所示。

第四步,将类库的依赖信息粘贴到 pom.xml 文件的 <dependencies> 节点下,而后按下快捷键「Ctrl+S」保存。紧接着,依次展开 test → Java Resources → Libraries → Maven Dependencies 节点,你能够看到该类库已经悄悄地添加进来了。

②、 <exclusions> 主要用于排除依赖。

有时候,咱们引入的依赖中可能会包含一些不想要的依赖包,咱们想引入本身想要的,这时候就要用到排除依赖了。

使用 <exclusion> 的时候只须要指定 groupId 和 artifactId 就好了,并不须要 version,这是由于 groupId 和 artifactId 就能够定位某种类型的依赖。

③、 <scope> 用来控制依赖的范围。

test:测试依赖范围。典型的例子是 Jnuit,它只有在编译测试代码及运行测试的时候才须要。

compile:编译依赖范围(其实不止是编译,对测试、运行一样有效),缺省项,若是没有指定,就会默认使用该依赖范围。

provided:提供依赖范围。对编译和测试有效,但在运行时候无效。

runtime:运行时依赖范围。对测试和运行有效,但在编译时无效。

PS:若是不知道选哪种,缺省就对了。

4)构建配置

<build> 元素中包含了执行 Maven 构建周期目标所需的插件以及相关的配置。

<build>
       <finalName>test</finalName>
       <plugins>

           <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-compiler-plugin</artifactId>
               <version>2.3.2</version>
               <configuration>
                   <source>${jdk.version}</source>
                   <target>${jdk.version}</target>
               </configuration>
           </plugin>

       </plugins>

       <resources>
           <resource>
               <directory>src/main/java</directory>
               <includes>
                   <include>**/*.xml</include>
               </includes>
           </resource>
       </resources>
</build>
复制代码

①、<finalName>,打成 jar 包或者 war 包时的名称。上文中曾提到,项目打包后的输出目录为 ${basedir}/target

②、<plugins> 用于指定项目在构建过程当中使用的插件。

  • <groupId><artifactId><version> 用于肯定使用的插件。
  • <configuration>,该插件所须要的特殊配置。Maven 3 默认使用的是 JDK 1.5,本例中咱们使用了 JDK 1.8。

③、<resources> 描述了各个资源在 Maven 项目中的具体路径。

  • <directory>,资源文件的路径,默认位于 ${basedir}/src/main/resources/ 目录下。
  • <includes>,用于指定在构建过程当中被处理的资源文件;对应 <excludes> 用于省去不被处理的资源文件。

0五、使用 Maven 对项目进行清理、编译、测试、打包

1)清理:mvn clean,该命令会删除 target 目录。能够直接在命令行中执行该命令,只须要切换到项目所在的路径下便可。

2)编译:mvn complie,该命令会编译 src/main/java 目录下的源码。同时,Maven 还会处理在 src/main/resources 目录下的资源文件,确保它们做为编译的一部分。

不过,很遗憾的是,执行该命令会报错。该命令给出的提示是,查看 [Help 1] 给出的地址,我尝试了一下,能够将 mvn complie 命令替换为 mvn compiler:compile 命令执行,结果以下图所示。

编译后能够在 target 目录下查看字节码文件。

3)测试:mvn test,test 命令在运行时,会执行 compile 命令;而以前咱们已经执行过一次 compile 命令,为了确保结果的准确性,能够执行 mvn clean test 命令确保测试以前没有残余物,结果以下图所示。

Maven 会经过 Surefire 插件,使用 pom.xml 文件中的测试提供者(一般是 Junit)运行测试。执行 test 命令不只会运行测试,还会产生报告文件,此时 target 目录下的截图以下:

4)打包:mvn install,该命令会按照 pom.xml 文件中 <packaging> 指定的方式(本例为 jar)对编译结果打包。同时,还会把打包好的文件放到本地的 Maven 仓库中,以便其余项目把它当作依赖项使用。命令执行结果以下图所示。

查看本地的 Maven 仓库,能够看到刚刚打包好的文件。

0六、最后

在 Maven 出现以前,流行的构建工具是 Ant;在 Maven 出现以后,还有一种新兴的构建工具 Gradle,它有意选择了和 Maven 相反的原则,不会强制使用者遵循刻板的构建周期。

总之,Maven 是一款优秀的构建工具,Java 项目的开发者颇有必要熟练地掌握它。


PS:扫码关注「沉默王二」公众号,回复关键字「0」获取二哥精心准备的程序员进阶电子书大礼包。

相关文章
相关标签/搜索