一文掌握Java开发工具Maven(简单上手)

掌握maven的相关知识是Java开发必备的技能,今天通过本文从入门安装开始,逐步深入讲解maven的相关知识,包括maven的安装到简单上手maven项目开发,感兴趣的朋友跟随小编一起看看吧

目录

Maven

1、安装maven

1.1 Windows安装

1.2 Linux安装

1.3 简单配置

1.4 idea配置

2、Maven简单上手

3、Maven生命周期

4、POM文件详解

4.1、基础介绍

4.2、dependencies&dependency

4.3、dependencyManagement

4.4、properties

4.5、构建配置

4.6、仓库配置

4.7、项目配置信息(了解即可)

5、Maven依赖

6、聚合和继承

6.1、使用idea创建聚合工程

6.2、使用idea创建分布式聚合工程

7、Maven插件

7.1 Spring Boot插件

 8、总结

9、参考

Maven

如果作为一个Java程序员,那么在日常的开发过程中,maven是很常见的项目构建工具。maven可以极大的提高我们的开发效率,帮助我们简化开发过程中一些解决依赖和项目部署的相关问题,所以学习掌握maven的相关知识是非常有必要的。

本文从入门安装开始,逐步深入讲解maven的相关知识。

1、安装maven

首先我们需要准备好安装包,这里推荐在官网下载:maven官网下载地址

我这里下载的是3.8.1版本的maven,不同版本的maven配置过程基本是一样的。

1.1 Windows安装

首先将maven安装包解压,根据自己的习惯选择解压目录,后续配置需要使用到解压的目录。我这里解压到了D:softwareMaven,之后的配置也是从这里开始的。

首先要配置Windows的环境变量,如果是最新版的Windows 10,那么右键单击属性后会出现如下页面,点击高级系统设置=>环境变量即可:

接下来就是配置系统变量,首先配置MAVEN_HOME,在系统变量窗口点击新建,然后输入变量名和变量值,变量名为MAVEN_HOME,变量值就是maven的安装路径,可以通过浏览目录找到自己的maven安装位置。

接下来配置系统变量中的path变量,首先选中path变量,然后点击编辑,弹出编辑path变量的窗口,点击新建,在最后一行输入如下参数:%MAVEN_HOME%bin

此时maven的环境变量已经配置完成了,可以打开cmd窗口,运行mvn -v查看配置是否成功。

1.2 Linux安装

将下载好的文件上传至云服务器,我这里直接上传到了/usr/local/目录下,然后直接将其解压

tar -zxvf apache-maven-3.8.1-bin.tar.gz

接下来就是配置环境变量,在/etc/profile文件添加环境变量,内容如下:

export MAVEN_HOME=/usr/local/apache-maven-3.8.1 export PATH=$PATH:$MAVEN_HOME/bin

然后再运行source /etc/profile使其生效即可。

然后可以运行mvn -v命令查看是否配置成功:

1.3 简单配置

当安装完maven以后,我们还需要配置maven的镜像和我们本地仓库的地址,maven的全局配置文件是安装目录下的conf/settings.xml文件,下面的配置都是在该文件中进行的。

1.3.1 配置本地仓库路径

本地仓库是我们新建maven项目并添加依赖后,那些依赖的jar包下载到的位置。

首先看看配置文件,本地仓库路径不配置的话认为当前用户目录下的./m2文件夹下的repository目录,我们最好自己配置下,管理maven仓库的位置。

配置的话选定自己的仓库目录,然后添加配置文件中即可,例如我这里是这样配置的:

D:softwareMavenMavenRepository

Linux的话需要注意路径的方式:

/usr/local/apache-maven-3.8.1/MavenRepository

1.3.2 配置镜像

如果我们不配置国内镜像的话,那么maven下载依赖可能会非常非常慢,所以我们这里要配置镜像,这里我配置的是阿里云的镜像:

alimavenaliyun mavenhttps://maven.aliyun.com/repository/publiccentral

当然也可以配置些其他的镜像,例如华为的镜像。

阿里云maven、华为云镜像

1.4 idea配置

我们通常都是使用idea进行项目的开发工作,所以这里接着介绍下idea如何配置我们自己安装的maven,而不是使用idea自带的maven。

首先点击Files->settins打开配置窗口:

然后找到maven的配置,将maven的安装路径配置文件以及本地仓库的配置均修改为我们自己安装的maven即可:

此外还要配置每个新建项目的maven配置,点击New Projects Settings -> Settings for New Projects:

也是进行相同的配置:

配置完成以后,我们以后就可以使用自己安装的maven在idea中开发项目了。

2、Maven简单上手

虽然我们可以使用idea简化项目的开发,但是我们还是要简单了解一下不借助idea如何新建maven项目的。

首先来看看maven的项目结构:

src |--main |--java 源代码目录 |--resources 资源目录 |--test |--java 测试代码目录 |--resources 测试资源目录 target |--classes 编译后的class文件目录 |--test-classes 编译后的测试class文件目录 pom.xml Maven工程配置文件

其中src、target、pom是同级目录,接下来我们尝试手动创建这些目录:

我们首先来看看pom.xml的基本配置:

4.0.0cn.wygandwdnlearn_maven1.0-SNAPSHOT

然后接着在src/java目录下新建一个Hello.java:

import java.util.*; class Hello { public static void main(String[] args) { System.out.println("Hello Maven"); } }

然后在项目的根目录下运行mvn compile试试,也就是src文件对应的目录:

出现BUILD SUCCESS就是构建成功了,接下来看看都构建出来了哪些文件

可以看出,maven自动为我们将Hello.java构建成了Hello.class并放到了target/classes目录下。

是不是很简单,当我们使用idea之后,这些工作都不需要我们来做,都是自动化完成的。

3、Maven生命周期

如果我们打开idea,查看maven的话,会发现maven的几个生命周期:

这些生命周期实际上分为三部分,分别是:

clean:为执行以下工作做必要的清理,就是删除out文件夹。

default:真正进行项目编译打包等工作的阶段

site: 生成项目报告,站点,发布站点

这三个生命周期又有各自详细的生命周期。

clean生命周期又分为如下几个阶段:

pre-clean:执行一些需要在clean之前完成的工作

clean:移除所有上一次构建生成文件

post-clean:执行一些需要在clean之后立刻完成的工作

default又分为如下几个阶段(和idea中显示的正好对应,这是简化版的生命周期):

validate:验证项目是否正确,所有必要的信息是否可用

compile:编译项目的源代码test:使用合适的单元测试框架测试编译的源代码,测试代码不应该被打包或者部署

package:将编译后的代码打包成可发布的格式,例如jar包

verify:运行任意的检查来验证项目包是否有效且达到质量标准

install:安装项目包到本地仓库,这样项目包可以用做其他本地项目的依赖

deploy:将最终的项目包复制到远程仓库与其他开发者和项目共享

site生命周期又分为如下几个阶段:

pre-site:执行一些需要在生成站点文档之前完成的工作

site:生成项目的站点文档

post-site: 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备

site-deploy:将生成站点文档部署到特定的服务器上

各个生命周期相互独立,互不影响,一个生命周期的阶段前后依赖。

当我们运行maven命令时,例如运行mvn compile,只有该阶段之前以及包括该阶段在内的所有阶段才会被执行,在compile之后的test、package等是不会被执行的。

常用的maven命令:

命令

说明

mvn -v

显示版本信息

mvn clean

清理项目产生的临时文件,一般是模块下的target目录

mvn compile

编译源代码,一般编译模块下的src/main/java目录

mvn package

项目打包工具,会在target目录下生成jar包或者war包

mvn test

测试命令,或执行src/test/java/下junit的测试用例

mvn install

将打包的jar/war文件复制到本地仓库,供其他模块使用

mvn deploy

将打包的文件发布到远程服务器,供其他人员下载依赖

mvn site

生成项目相关信息的网站

mvn dependency:tree

打印出项目的整个依赖树

mvn archetype:generate

创建maven的普通Java项目

4、POM文件详解

4.1、基础介绍

首先我们来看看一个简单的POM文件

4.0.0cn.wygandwdnlearn_maven1.0-SNAPSHOTpom

这是maven项目构建后产生的最基础的pom文件,接下来讲讲这几个标签的含义:

modelVersion:描述pom文件遵循哪个版本的项目描述符,描述了当前pom模型的版本,对于maven2和maven3来说,它只能是4.0.0;它是强制性的

接下来的groupId、artifactId、version是唯一定位一个项目的,相当于项目的坐标:

groupId:团体组织的标识符,它以创建这个项目的组织名称的逆向域名开头,例如我们域名为wygandwdn.cn,这里就是cd.wygandwdn,同时也对应着Java的包结构

artifactId:单独项目的标识符,一个组织可能会有多个项目,那么这个artifactId就是描述一个组织名下的不同项目,不要在artifactId中包含点号(.)

version:项目的版本packing:项目的打包类型,认为jar,描述了项目打包后的输出。类型为jar的项目产生一个jar文件,类型war的项目产生一个web应用;类型为pom的话,说明该项目为一个聚合项目,包含多个子项目

Maven的version中通常出现如下几个特殊的字符串:SNAPSHOT、LATEST、RELEASE,例如我们使用idea创建的认maven项目的版本通常为:1.0-SNAPSHOT。各个版本的含义和逻辑为:

SNAPSHOT:表示项目开发过程中的快照版本,不稳定的版本

LATEST:某个特定构件的最新版本,这个发布可能是一个发布版,也可能是一个snapshot版本,具体看哪个时间最后

RELEASE:指最后一个发布版,稳定版

4.2、dependencies&dependency

我们之前说过,maven最终的功能就是管理依赖,那么这些依赖就是通过dependencies&dependency标签来定义的。

例如:

4.0.0cn.wygandwdnlearn_maven1.0-SNAPSHOTpomjunitjunit4.12jarcompliefalSEOrg.slf4jslf4j-api

上面的groupId、artifactId、version是定位jar包的坐标,通过这个唯一的标识,maven会自动去仓库引入依赖。

type:代表项目依赖的类型,例如jar、war、pom等。

scope:代表的是这些依赖的作用范围,分别如下:

compile(认编译范围):该范围是认依赖范围,此依赖范围对于编译、测试、运行三种classpath都有效,也就是说该范围下的jar包在编译、测试、运行和打包时都可以使用。

test(测试依赖范围):test范围的依赖只对测试classpath有效,在编译主代码和项目运行时,都将无法使用该依赖,最典型的例子就是junit。junit是测试时才需要的依赖,所以它的依赖范围需要指定为test。如果不加范围也不会报错,但是该依赖会被加入到编译和运行的classpath中,会浪费一定的空间

junitjunit4.7test

provided(已提供依赖):使用该依赖范围时,只对编译和测试的classpath有效,对运行时classpath无效,最典型的例子就是servlet-api,编译和测试项目时都需要该依赖,但是在运行时,web容器已经提供该依赖,所以运行时就不需要此以爱,如果不显示指定该依赖范围,并且容器依赖的版本和maven不一致的话,可能会造成冲突。

javax.servletjavax.servlet-api4.0.1provided

runtime(运行时依赖范围):使用该依赖范围时,只对测试和运行的classpath有效,对编译时的classpath无效,典型的例子就是jdbc驱动的实现,项目主代码编译的时候只需要jdk提供的jdbc接口,只有在测试和运行时才需要实现上述接口的具体jdbc驱动。

MysqLmysql-connector-java5.1.25runtime

optional:设置依赖是否可选,认为false,即子项目认都继承。如果为true,则子项目必需显示的引入

exclusions:该标签主要用于依赖的排除,该标签包含s,说明可以排除多个依赖,具体排除的依赖通过exclusion标签定义,exclusion中通过groupId和artifactId定位要排除的依赖。

4.3、dependencyManagement

dependencyManagement通常会在父工程中定义,目的就是为了统一各个子模块的依赖版本,也就是管理子项目中依赖的jar包的版本。

标签只是声明依赖,并不是实际的引入

子项目需要显式的声明需要用的依赖,如果不再子项目中声明依赖,那么子项目是不会从父项目中继承依赖的

只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本

在我们创建聚合工程时,使用该标签非常有用

4.4、properties

properties定义了一些在pom中使用的占位符,相当于一些公共的属性,一般用于指定各个依赖的版本号。

例如:

4.0.0cn.wygandwdnlearn_maven1.0-SNAPSHOTpom8.0.22MysqLmysql-connector-java${MysqL.version}

当我们定义MysqL连接依赖时,将其对应的版本通过properties来定义,那么以后修改MysqL连接依赖时,只需要修改标签中的依赖即可,不需要再去对应的依赖处修改

properties标签内一般根据依赖的名称自定义标签,通过"."进行分割,然后在dependency中引入即可。

当我们引入众多的依赖时,使用properties非常有用,通过properties定义版本,那么修改时,只统一修改这里的版本即可。其子项目也可以使用properties里定义的标签

4.5、构建配置

来看看build标签下的内容

myPorjectName${basedir}/target${basedir}srcmainjava${basedir}srctestjava${basedir}targetclasses${basedir}targettest-classessrc/main/java**/*.properties**/*.xml**/*.propertiesfalsesrc/main/resources**/*.properties**/*.xmlfalse...

resources主要处理资源过滤的问题,这里详细解释下resource标签下的各个属性

directory:资源过滤对应的目录

includes:资源过滤对哪些资源生效

excludes:资源过滤对哪些资源不生效

filtering:true或者false(具体情况可以自己在实际项目中测验一下,这里直接给出测验后的结论)

true就是对includes下定义的资源过滤,对excludes下定义的资源不过滤

false就是对includes下定义的资源不过滤,对excludes下定义的资源过滤

当我们想引入支付包的jar包或者oracle的连接驱动时,可以自己配置jar包的路径,然后引入项目,具体的配置如下:

org.apache.maven.pluginsmaven-compiler-plugintrue1.81.8UTF-8${project.basedir}/src/main/webapp/WEB-INF/lib

从这里我们可以看出,不管是引入依赖,还是引入插件,都是通过groupId、artifactId进行唯一的标识,来确定我们引入的具体的依赖或者插件

4.6、仓库配置

alimavenaliyun mavenhttp://maven.aliyun.com/nexus/content/groups/public/truefalse

pom.xml里面的仓库与setting.xml里的仓库功能是一样的。主要的区别在于,pom里的仓库是个性化的。比如一 家大公司里的setting文件是公用的,所有项目都用一个setting文件,但各个子项目却会引用不同的第三方库,所 以就需要在pom.xml里设置自己需要的仓库地址。

4.7、项目配置信息(了解即可)

banSEOn-maven http://www.clf.com/ A maven project to study maven. Demo clf@126.com clf@126.com clf@126.com http:/hi.clf.com/ HELLO WORLD banSEOn banSEOn@126.com Project ManagerArchitect demohttp://hi.clf.com/ No -5 Apache 2 http://www.clf.com/LICENSE-2.0.txt repo Abusiness-friendly OSS license demo http://www.clf.com/

还有其他很多,想要了解的可以去官网看看更加详细的版本。

5、Maven依赖

Maven给我们带来的最大的便利就是自动帮我们下载并且管理依赖,我们不必再向之前那样自己在网上寻找各种依赖,导入工程中;这大大简化了我们的开发工作,提高了效率。

接下来我们来看看maven如何解决依赖问题。

当我们在maven的pom配置文件中引入依赖后,也就是在中配置后,maven会自动帮我们下载我们所需要的依赖。

那么这个依赖是如何下载的呢?

通过上图我们可以发现,当maven项目导入依赖之后,首先从本地仓库查找依赖,找不到则取远程仓库查找,这里去远程仓库就用到了我们之前配置的镜像。

如果在公司内部,电脑无法联网,那么可能查完本地会去私服查找依赖,这个私服既在局域网内部,又可以连接外网,而且在局域网内部下载相当快。私服的配置一般通过nexus来完成的。

在开发过程中,我们的项目可以依赖第三方的jar包,那么第三方的jar包也可以依赖其他人的jar包,那么如果依赖重复了,maven如何解决依赖的传递性呢,它有如下几种原则:

最短路径优先:如果A依赖B,B依赖C,而且A和B同时依赖于D,并且两个版本不一致,那么根据最短路径优先原则来看,我们的项目依赖的是A依赖的D

路径相同先声明原则:如果我们的工程同时依赖于A和B,而且A和B都依赖D,且版本不一致,那么谁先声明项目就依赖哪个版本的D

当我们不想要某个jar包依赖的jar包时,我们可以通过exclusions来排除jar包的依赖。

6、聚合和继承

在项目开发过程中,我们通常使用maven构建一个整体的项目,然后在其中构建不同的子模块进行开发工作,那么这些父子工程就对应了聚合和继承。

对于聚合和继承,有两个关键的标签,分别是parent和modules:

parent:定义模块的父工程,其中根据groudId和artifactId来定位父工程

modules:描述父工程包含的子工程的名称

可以被继承的元素如下:

可以被继承的POM元素如下:

groupId:项目组ID,项目坐标的核心元素

version:项目版本,项目坐标的核心因素

properties:自定义的Maven属性 一般用于同一制定各个依赖的版本号

dependencies:项目的依赖配置 公共的依赖

dependencyManagement:项目的依赖管理配置

repositories:项目的仓库配置

build:包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等

此外还有一些项目的描述信息也可以被继承:

description:项目的描述信息

organization:项目的组织信息

inceptionYear:项目的创始年份

url:项目的URL地址

developers:项目的开发者信息

contributors:项目的贡献者信息

distributionManagement:项目的部署配置

issueManagement:项目的缺陷跟踪系统信息

ciManagement:项目的持续集成系统信息

scm:项目的版本控制系统

malilingLists:项目的邮件列表信息

reporting:包括项目的报告输出目录配置、报告插件配置等

6.1、使用idea创建聚合工程

首先选择新建maven项目:

不选择任何模板,直接next,然后给定项目的名称,点击finish即可完成项目的创建:

项目创建完成后可以删除对应的src目录,因为我们要创建子模块,不会在这个父工程中写代码

然后右键项目名,选择新建module:

选择父模块,并且填写相关的信息:

当新建完成以后,我们看看两个工程的pom文件

可以看到对应的父子信息了。

6.2、使用idea创建分布式聚合工程

当我们创建分布式项目时,往往都是创建一个maven项目,然后在其下面创建不同的子模块。这些子模块有可能是spring boot项目,如果使用idea的Spring Initializr创建的话,那么认父项目为:

org.springframework.bootspring-boot-starter-parent2.3.1.RELEASE

这个认的父项目为我们定义了各种各样的依赖版本,我们在开发过程中可以很轻松的解决版本相关的问题。

但是这样的话,我们统一创建的maven项目就没有意义了,那么我们如何解决这个问题呢?

如果我们查看这个父工程的话,可以发现它的父工程为:

我们再看看spring-boot-dependencies:

其实这个spring-boot-dependencies已经为我们定义好了各种版本依赖,那么真正解决版本问题的实际上就是spring-boot-dependencies,所以如果我们在父maven项目中依赖了spring-boot-dependencies,那么也可以进行版本的配置管理,不用担心复杂的版本问题,所以我们可以使用如下方式新建分布式项目。

首先创建一个maven项目,并将src目录删除

在pom目录中引入spring-boot-dependencies依赖

创建maven子项目,然后在子项目中自行引入相关的依赖即可。

这里我们使用spring-boot-dependencies进行了版本的管理。

那么对应的父工程pom文件为:

4.0.0cn.wygandwdnmicro_officialpom1.0-SNAPSHOTmicro_official_news888.0.222.1.41.18.202.4.51.2.47org.springframework.bootspring-boot-dependencies${spring.boot.dependencies.version}pomimportorg.mybatis.spring.bootmybatis-spring-boot-starter${mybatis-spring-boot-starter.version}MysqLmysql-connector-java${mysql-connector-java.version}runtimeorg.projectlomboklombok${lombok.version}providedcom.alibabafastjson${fastjson.version}

子工程pom文件为:

4.0.0cn.wygandwdnmicro_official1.0-SNAPSHOTmicro_official_newsmicro_official_newsnews1.8org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-testtestorg.springframework.bootspring-boot-maven-plugin

7、Maven插件

Maven实际上是依赖插件执行的框架,每个任务实际上是由插件完成的,Maven插件通常被用来:

jar包

创建war包

编译代码文件

代码单元测试

创建工程文档、工程报告等

插件通常提供了一个目标的集合,并且可以使用下面的语法执行:

mvn [plugin-name]:[goal-name]

例如,一个 Java 工程可以使用 maven-compiler-plugin 的 compile-goal 编译,使用以下命令:

mvn compiler:compile

7.1 Spring Boot插件

org.springframework.bootspring-boot-maven-plugin

Spring Boot的Maven插件(Spring Boot Maven plugin)能够以Maven的方式为应用提供Spring Boot的支持,即为Spring Boot应用提供了执行Maven操作的可能。

Spring Boot Maven plugin能够将Spring Boot应用打包为可执行的jar或war文件,然后以通常的方式运行Spring Boot应用。

Spring Boot Maven plugin的5个Goals

spring-boot:repackage,认goal。在mvn package之后,再次打包可执行的jar/war,同时保留mvn package生成的jar/war为.origin

spring-boot:run,运行Spring Boot应用

spring-boot:start,在mvn integration-test阶段,进行Spring Boot应用生命周期的管理

spring-boot:stop,在mvn integration-test阶段,进行Spring Boot应用生命周期的管理

spring-boot:build-info,生成Actuator使用的构建信息文件build-info.properties

 8、总结

maven还有很多知识,了解了这些基本的maven知识以后,其他相关的知识也可以很快掌握。

更多有关maven的知识可以参考官网,以上讲述的知识已经可以胜任我们日常的开发工作了。

9、参考

Maven官网

bilibili

尚硅谷

以上就是Java开发利器Maven的详细内容,更多关于Java开发工具maven的资料请关注编程之家其它相关文章

相关文章

HashMap是Java中最常用的集合类框架,也是Java语言中非常典型...
在EffectiveJava中的第 36条中建议 用 EnumSet 替代位字段,...
介绍 注解是JDK1.5版本开始引入的一个特性,用于对代码进行说...
介绍 LinkedList同时实现了List接口和Deque接口,也就是说它...
介绍 TreeSet和TreeMap在Java里有着相同的实现,前者仅仅是对...
HashMap为什么线程不安全 put的不安全 由于多线程对HashMap进...