大家好,我是二哥呀!
今天来给大家介绍一款项目构建神器——Maven,不仅能帮我们自动化构建,还能够抽象构建过程,提供构建任务实现;它跨平台,对外提供了一致的操作接口,这一切足以使它成为优秀的、流行的构建工具,从此以后,再也不用担心项目搞崩了。
由于公众号的文章发布后不能修改,也没办法加个统一的目录作为索引页,所以我就把《Java 程序员进阶之路》的系列文章开源到了 GitHub(点击阅读原文可以直接跳转):
https://github.com/itwanger/toBeBetterJavaer
每天看着 star 数的上涨我心里非常的开心,希望越来越多的 Java 爱好者能因为这个开源项目而受益,而越来越多人的 star,也会激励我继续更新下去~
总结一下 Maven 的优点,主要有以下 3 点:
由于 JDK 是 Maven 安装的前置条件,所以请使用 java -version 确认是否已经安装了 JDK:
我本人使用的是 macOS,所以可以有两种安装方式,一种官网下载,手动安装;一种直接使用 brew 一键安装。
我们先介绍官网下载,手动安装,该方式同样适用于 Windows 系统,差别可参照 Maven 官网安装教程:
http://maven.apache.org/install.html
1)一种官网下载,手动安装
第一步,去官网下载 Maven 安装包:
官网地址:http://maven.apache.org/download.cgi
很多初学者在官网下载的时候不知道选哪一个,这里做一下简单的介绍。
第二步,解压下载的安装包,复制该路径:
~/.m2/ 目录下(~表示用户目录),修改该文件可以在用户范围内定制 Maven 的行为。第三步,配置环境变量
打开终端,输入 vim ~/.bash_profile 命令打开 bash_profile 文件:
bash_profile 文件用于配置环境变量和启动程序,详细介绍可参照:
https://www.cnblogs.com/kevingrace/p/8072860.html
在文件中添加设置环境变量的命令:
export M2_HOME=/Users/maweiqing/cmower/save/apache-maven-3.8.3
export PATH=${PATH}:${M2_HOME}/bin
保存后退出,可以执行 source ~/.bash_profile 使配置生效:
第四步,查看配置是否生效
输入 mvn -v 命令,如果输出以下内容,表示配置成功:
如未生效,可再开一个终端窗口尝试 mvn -v 命令。
2)brew 一键安装
第一步,使用 brew install maven 命令一键安装,并自动配置环境变量
第二步,使用 mvn -v 命令查看版本
Maven 是基于 POM(Project Object Model) 进行的,项目的所有配置都会放在 pom.xml 文件中,包括项目的类型、名字,依赖关系,插件定制等等。
<?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.itwanger</groupId>
<artifactId>MavenDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>MavenDemo</name>
</project>
groupId、artifactId和version这三个元素定义了一个项目的基本坐标,在Maven的世界里,任何的jar和pom都是以基于这些坐标进行区分的。
<project>
...
<dependencies>
<dependency>
<groupId>实际项目</groupId>
<artifactId>模块</artifactId>
<version>版本</version>
<type>依赖类型</type>
<scope>依赖范围</scope>
<optional>依赖是否可选</optional>
<!—主要用于排除传递性依赖-->
<exclusions>
<exclusion>
<groupId>…</groupId>
<artifactId>…</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependencies>
...
</project>
依赖范围有以下几种:
关于传递性依赖:
比如一个account-email项目为例,account-email有一个compile范围的spring-code依赖,spring-code有一个compile范围的commons-logging依赖,那么commons-logging就会成为account-email的compile的范围依赖,commons-logging是account-email的一个传递性依赖:
有了传递性依赖机制,在使用Spring Framework的时候就不用去考虑它依赖了什么,也不用担心引入多余的依赖。Maven会解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目中。
关于依赖可选:
项目中A依赖B,B依赖于X和Y,如果所有这三个的范围都是compile的话,那么X和Y就是A的compile范围的传递性依赖,但是如果我想X、Y不作为A的传递性依赖,不给它用的话,可以按照下面的方式配置可选依赖:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.itwanger</groupId>
<artifactId>project-b</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.10</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</groupId>
<version>8.4-701.jdbc3</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>
关于依赖排除:
有时候你引入的依赖中包含你不想要的依赖包,你想引入自己想要的,这时候就要用到排除依赖了,比如下图中spring-boot-starter-web自带了logback这个日志包,我想引入log4j2的,所以我先排除掉logback的依赖包,再引入想要的包就行了。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.5.6</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 使用 log4j2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.5.6</version>
</dependency>
声明exclustion的时候只需要groupId和artifactId,不需要version元素,因为groupId和artifactId就能唯一定位某个依赖。
在 Maven 的术语中,仓库是一个位置(place),项目中依赖的第三方库以及插件(可统称为构件),都放在这里。所有的 Maven 项目都可以共享这个仓库,只需要根据依赖的坐标,就可以在需要的时候找到仓库中的依赖,并使用它们。
举个例子,项目中使用了分页插件的依赖:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
那么它对应的仓库路径是这样的:
仓库可以以下几种:
1)本地仓库
当Maven在执行编译或测试时,如果需要使用依赖文件,它总是基于坐标使用本地仓库的依赖文件。
默认情况下,不管是Window还是macOS,或者是 Linux,每个用户都会在自己的用户目录下有一个路径名为 .m2/repository/ 的仓库目录。
如果你想自定义本地仓库目录地址,可以编辑文件~/.m2/settings.xml,设置localRepository元素的值为你想要的仓库地址,例如:
<localRepository>/path/to/local/repo</localRepository>
如果找不到 ~/.m2/settings.xml 的话,可以到 Maven 的安装目录(前文提到的 conf 目录)下去拷贝。
2)远程仓库
默认情况下,本地仓库是被注释掉的,也就是空的,那么就必须得给 Maven 配置一个可用的远程仓库,否则 Maven 在 build(构建)的时候就无法去下载依赖。
中央仓库就是这样一个可用的远程仓库,里面包含了这个世界上绝大多数流行的开源 Java 类库,以及源码、作者信息、许可证信息等等。
不过,默认的中央仓库访问速度比较慢,通常我们会选择使用阿里的 Maven 远程仓库。
<repositories>
<repository>
<id>ali-maven</id>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
</repository>
</repositories>
搭建远程仓库的另外一个目的是方便部署我们自己的项目构件至远程仓库供其他团队成员使用,这时候需要配置distributionManagement元素:
<distributionManagement>
<repository>
<id>releases</id>
<name>public</name>
<url>http://59.50.95.66:8081/nexus/content/repositories/releases</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>Snapshots</name>
<url>http://59.50.95.66:8081/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
配置好了以后运行命令 mvn clean deploy,Maven就会将项目部署到对应的远程仓库。项目是快照还是发布版本通过之前远程仓库配置项中的 releases 和 snapshots 来区分。
3)仓库镜像
如果仓库X可以提供仓库Y存储的所有内容,那么就可以认为X是Y的一个镜像。通常我们会在 settings.xml 文件中添加阿里云镜像:
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
其中 mirrorOf 元素的可选项有:
<mirrorOf>*</mirrorOf>,匹配所有远程仓库。<mirrorOf>external:*</mirrorOf>,匹配所有远程仓库,使用localhost的除外,使用 file:// 协议的除外。也就是说,匹配所有不在本机上的远程仓库。<mirrorOf>repo1,repo2</mirrorOf>,匹配仓库repo1和repo2,使用逗号分隔多个远程仓库。<mirrorOf>*,!repo1<mirrorOf>,匹配所有远程仓库,repo1除外,使用感叹号将仓库从匹配中排除。上例中 <mirrorOf>central</mirrorOf> 表示任何对于中央仓库的请求都会转至该镜像。
4)私服
私服是一种特殊的远程仓库,它架设在局域网内中,私服代理广域网上的远程仓库,供局域网内的Maven用户使用。当Maven需要下载构件的时候,先从私服请求,如果私服上不存在该构件,则从外部的远程仓库下载,并缓存到私服上。
私服有以下好处:
5)仓库服务搜索
推荐 2 个提供仓库搜索服务的网站:
Sonatype Nexus:https://repository.sonatype.org/ MVNrepository:http://mvnrepository.com/
1)Maven 常见命令
mvn clean:表示运行清理操作(会默认把target文件夹中的数据清理)。mvn clean compile:表示先运行清理之后运行编译,会将代码编译到target文件夹中。mvn clean test:运行清理和测试。mvn clean package:运行清理和打包。mvn clean install:运行清理和安装,会将打好的包安装到本地仓库中,以便其他的项目可以调用。mvn clean deploy:运行清理和发布(发布到私服上面)。2)Maven 常用 POM 属性
${project.build.sourceDirectory}:项目的主源码目录,默认为src/main/java/${project.build.testSourceDirectory}:项目的测试源码目录,默认为 /src/test/java/${project.build.directory}:项目构建输出目录,默认为 target/${project.build.outputDirectory}:项目主代码编译输出目录,默认为 target/classes/${project.build.testOutputDirectory}:项目测试代码编译输出目录,默认为 target/testclasses/${project.groupId}:项目的 groupId.${project.artifactId}:项目的 artifactId.${project.version}:项目的 version,于 ${version} 等价${project.build.finalName}:项目打包输出文件的名称,默认为${project.artifactId}${project.version}3)Intellij IDEA 配置 Maven
4)Maven 常用插件
插件是Maven的核心功能,它允许在多个项目中重用通用的构建逻辑。插件可用于:
常用的插件有:
希望你能在阅读完本篇文章后对 Maven 有一个初步的了解和掌握,并将这些技能在项目的实战中加以练习,以达到项目工程化的要求。
参考链接:
嘟嘟MD:http://tengj.top/2018/01/01/maven/
杭建:《Java 工程师修炼之道》
许晓斌:https://www.infoq.cn/article/2011/04/xxb-maven-7-plugin
这是《Java 程序员进阶之路》专栏的第 71 篇(记得点击「阅读原文」链接去点个 star 哦)。该专栏风趣幽默、通俗易懂,对 Java 爱好者极度友好和舒适😄,内容包括但不限于 Java 基础、Java 集合框架、Java IO、Java 并发编程、Java 虚拟机、Java 企业级开发(SSM、Spring Boot)等核心知识点。
点击上方名片,发送消息「03」 就可以获取最新版《Java 程序员进阶之路》PDF 版了,让我们一起成为更好的 Java 工程师吧,冲!