Maven 是 Apache 软件基金会组织维护的一款自动化构建工具,专注服务于 Java 平台的项目构建和 依赖管理。将项目开发和管理过程抽象成一个项目对象模型(POM)。
下载地址:Maven – Download Apache Maven
maven 的使用需要在系统中配置,如下环境变量,这些配置可以在:bin目录下的mvn文件中看到:
JAVA_HOME:
MAVEN_HOME
Ant是第一个所谓的“现代构建工具”,用于自动化构建过程。它是用Java实现的,主要用于Java项目。Ant的第一个公开发行版是在2000年,它很快成为Java项目最流行的构建工具,这要归功于它的平台独立性(如Java),设置门槛低,并提供可重复的构建。后来,它还获得了接受插件的能力。
Maven于2004年首次发布,旨在改进开发人员在使用Ant和其他构建工具时遇到的一些问题。Maven最大的成就被认为是引入了项目结构约定、依赖关系管理和一个中心工件库Maven central。
Maven仍然使用XML来编写构建文件(pom.XML),但是结构非常不同,因为它变成了声明性的。现在,开发人员不必写下导致某些目标的所有命令,而是描述项目的结构(如果它与约定不同的话),Maven本身提供了程序员可以调用的可用目标。另外,Maven能够通过网络下载依赖项。
Gradle是三个构建工具中最年轻的一个,它的开发人员试图将Ant的能力和灵活性与Maven的依赖关系管理和约定结合起来,以创建漂亮而闪亮的构建工具。经过几年的开发,GradleV1.0于2012年发布,并迅速开始流行起来。它发展得非常快,已经被一些大企业采用——例如,Gradle被选为谷歌Android操作系统的构建工具。
注意:运行Maven命令时一定要进入pom.xml文件所在的目录!
在maven世界中,任何一个依赖,插件或者项目构建的输出,都可以成为构件。
maven在某个位置统一存储所有Maven项目共享的构建,这个统一的位置就是仓库。
maven项目只需要声明这些依赖的坐标,在需要的时候(如:编译时)maven会自动根据坐标找到仓库中的构件,并使用他们。为了实现重用,项目构建完毕后生成的构建也可以安装或部署到仓库中,供其他项目使用。
当maven根据坐标寻找构件的时候,它首先会查看本地仓库,如果本地仓库存在此构件,就直接使用。如果本地不存在此构件,或者需要查看是否有更新的构建版本,maven就会去远程仓库中寻找,发现需要的构件之后下载到本地仓库之后再使用。如果本地和远程都没有需要的构建maven就会报错。
中央仓库是maven自带的远程仓库,它包含了绝大部分开源的构建。在默认配置中,当本地仓库没有maven需要的构件的时候,他就会从中央仓库下载。
私服:私服是另一种特殊的远程仓库,为了节省时间和宽带。应该在局域网内架设一个私有的仓库服务器,用于代理所有外部的远程仓库。内部的项目还能部署到私服上供其他项目使用。
参考:Maven私服仓库配置-Nexus详解_nexus 仓库配置
依赖管理系统 maven为java世界引入了一个新的依赖管理系统jar包管理jar升级时修改配置文件即可,在java世界中,可以用groupid,artifactid,version组成的Coordination(做标)唯一标识一个依赖。
任何基于Maven构建的项目自身也必须定义这三项属性,生成的包可以是jar包,也可以是war包或者jar包。
①groupId:定义当前Maven项目隶属的实际项目–公司名称。
②artifactId:该元素定义实际项目中的一个Maven模块–项目名。推荐的做法是使用实际项目名称作为artifactId的前缀。比如:spring-bean,spring-webmvc等。
③version:该元素定义maven项目当前所处的版本。
多模块构建 项目复查时dao service controller 层分离将一个项目分解为多个模块已经是很通用的一种方式。
在maven中需要定义一个parent POM作为一组module的聚合POM,在该POM中可以标签来定义一组子模块,parent POM不会有什么实际构建产生。而parent POM中的build配置以及依赖配置都会自动继承给子module。
一致的项目构建 主要解决了我们在idea中和eclipse中创建的项目,目录可能不一样,但是如果使用了maven后,我们创建的项目目录都是一样的。 Maven在设计之初的理念就是Conversion over configuration(约定大于配置) ,其制定了一套项目目录结构作为标准的java项目结构,解决不同ide带来的文件目录不一致问题。
通过统一的pom.xml文件来配置tomcat、jetty等插件,非常方便。比如之前构建一个web项目还要各种配置tomcat服务器等的,就很麻烦。
org.mortbay.jetty
maven-jetty-plugin
6.1.25
10
/test
构建就是以我们编写的 Java 代码、框架配置文件、国际化等其他资源文件、如:页面和图片等静态资源作为“原材料”,去“生产”出一个可以运行的项目的过程。
构建过程的几个主要环节
①清理:删除以前的编译结果,为重新编译做好准备。
②编译:将 Java 源程序编译为字节码文件。
③测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。
④报告:在每一次测试后以标准的格式记录和展示测试结果。
⑤打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java 工程对应 jar 包,Web 工程对应 war 包。
⑥安装:在 Maven 环境下特指将打包的结果——jar 包或 war 包安装到本地仓库中。
⑦部署:将打包的结果部署到远程仓库或将 war 包部署到服务器上运行。
Maven的生命周期是一个抽象的概念,并不具体指某个操作,是Maven经过长时间思考和分析后总结出来的。它包括了一个项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等一系列的构建流程。
但它仅仅是抽象而已,并不执行具体操作,它的具体操作是交给Maven的各种插件来实现,所以说生命周期和插件是密不可分的。
Maven的生命周期并不像我们所想的是一条线,它实际上有3套相互独立的生命周期,分别是:clean、default和site。
而这三套生命周期,又各自都有一些不同的阶段(phase),这些阶段就是生命周期中最细化的操作,当然它仍然是抽象概念,具体操作是给插件做的。
下面具体的说明这3个生命周期的各个阶段,注意是有顺序的,各个阶段之间的顺序也是如下的顺序
用于清理项目,clean 生命周期包括以下 3 个阶段:
default 生命周期定义了项目真正构建时所需要的所有步骤,它是所有生命周期中最核心,最重要的部分.
各阶段如下表:
site生命周期的目的是建立和发布项目站点,maven能够基于POM所包含的信息,自动生成一个友好的站点,方便团队交流和发布项目信息。
site 生命周期包含以下 4 个阶段:
每套生命周期包含一系列的构建阶段(phase),这些阶段是有顺序的,且后面的阶段依赖于前面的阶段。用户与 Maven 最直接的交互方式就是调用这些生命周期阶段。
以 clean 生命周期为例,它包含 pre-clean、clean 以及 post-clean 三个阶段,当用户调用 pre-clean 阶段时,则只有 pre-clean 阶段执行;当用户调用 clean 阶段时,pre-clean 和 clean 阶段都会执行。当用户调用 post-clean 阶段时,则 pre-clean、clean 以及 post-clean 三个阶段都会执行。
三套生命周期本身是相互独立的,用户可以只调用 clean 生命周期的某个阶段,也可以只调用 default 生命周期的某个阶段,而不会对其他生命周期造成任何影响。当然也可以同时调用两套生命周期的某个阶段。
通过将阶段名传递给 mvn 命令,就可以调用构建阶段,例如:
mvn clean,就是调用clean生命周期的clean阶段,当前项目的target目录会被清空。
maven 中内置的预定义,用户可以直接使用 常见于项目的根配置文件,这里说的是顶级根,如:
${basedir}表示项目根目录,即包含pom.xml文件的目录;
${version}表示项目版本;
${project.basedir}同${basedir};
${project.baseUri}表示项目文件地址;
${maven.build.timestamp}表示项目构件开始时间;
${maven.build.timestamp.format}表示属性${maven.build.timestamp}的展示格式,默认值为yyyyMMdd-HHmm,可自定义其格式,其类型可参考java.text.SimpleDateFormat。用法如下:
yyyy-MM-dd HH:mm:ss
pom 中对应元素的值
常用的pom属性值有:
${project.build.directory}表示主源码路径;
${project.build.sourceEncoding}表示主源码的编码格式;
${project.build.sourceDirectory}表示主源码路径;
${project.build.finalName}表示输出文件名称;
${project.version}表示项目版本,与${version}相同;
在pom.xml文件的标签下定义的Maven属性
xiaoming
在其他地方使用${my.pro}使用该属性值。
与pom属性同理,用户使用以settings.开头的属性引用settings.xml文件中的XML元素值)
${settings.localRepository}表示本地仓库的地址;
所有Java系统属性都可以使用Maven属性引用,例如{user.home}指向了用户目录。可以通过命令行mvn help:system查看所有的Java系统属性。
在Java代码中引用Maven属性
在Java代码中,我们可以使用System.getProperty()方法来获取Maven属性的值。System.getProperty()方法接受一个字符串参数,该参数是要获取的属性的键。
例如,要获取在pom.xml中定义的java.version属性的值,可以使用以下代码:
String javaVersion = System.getProperty("java.version");
System.out.println("Java版本:" + javaVersion);
所有环境变量都可以使用以env.开头的Maven属性引用。例如${env.JAVA_HOME}指代了JAVA_HOME环境变量的值。也可以通过命令行mvn help:system查看所有环境变量。
jdbc:mysql://127.1.1.1:3306/ssm_db
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=${jdbc.url}
jdbc.username=root
jdbc.password=root
Maven在默认情况下是从当前项目的src\main\resources
下读取文件进行打包。
${project.basedir}/src/main/resources
true
module 项目方式时,可在顶级pom 下统一配置。
在我们jar包的版本定义中,有两个工程版本用的比较多:
1. 项目开发过程中临时输出的版本,称为快照版本
2. 快照版本会随着开发的进展不断更新
1. 项目开发到一定阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构件文件是稳定的
2. 即便进行功能的后续开发,也不会改变当前发布版本内容,这种版本称为发布版本
4.0.0
asia.banseon
banseon-maven2
jar
1.0-SNAPSHOT
banseon-maven
http://www.baidu.com/banseon
A maven project to study maven.
jira
http://jira.xxxx.com/xxxx
Demo
[email protected]
[email protected]
[email protected]
http://localhost:8080/demo/dev/
HELLO WORLD
youname
[email protected]
Project Manager
Architect
demo
http://www.xxx.com/
No
+8
Apache 2
http://www.xxxx.com/LICENSE-2.0.txt
repo
A business-friendly OSS license
scm:svn:http://svn.xxxx.com/maven/xxxxx-maven2-trunk(dao-trunk)
scm:svn:http://svn.xxxx.com/maven/dao-trunk
http://svn.xxxxx.com/
demo
http://www.xxxxxx.com/
......
......
Windows XP
Windows
x64
6.1.7100
mavenVersion
2.0.3
/usr/local/xxxx/xxxx-home/tomcat/maven-guide-zh-to-production/workspace/
/usr/local/xxxx/xxxx-home/tomcat/maven-guide-zh-to-production/workspace/
......
......
......
......
......
......
banseon-repository-proxy
banseon-repository-proxy
http://10.10.10.123:8080/repository/
default
......
org.apache.maven
maven-artifact
3.8.1
jar
test
spring-core
org.springframework
true
......
xxx-maven2
xxx maven2
file://${basedir}/target/deploy
xxx-maven2
xxx-maven2 Snapshot Repository
scp://svn.xxxx.com/xxx:/usr/local/maven-snapshot
banseon-site
business api website
scp://svn.baidu.com/xxx:/var/www/localhost/web
参见:【精选】Maven的settings.xml配置详解_maven setting配置-CSDN博客
直接依赖和间接依赖
A依赖B,B依赖于C
A和B之间就是直接依赖;
A和C之间就是间接依赖;
依赖关系具有传递性。
通过依赖传递关系,可以使依赖关系树迅速增长到一个很大的量级,但很有可能会出现依赖重复,依赖冲突等情况,Maven针对这些情况提供了如下功能进行处理:
A项目依赖于B项目,B项目中所依赖的jar包是compile范围;B项目中的依赖jar包就可以传递A项目中;
注意:scope定义了依赖的范围,默认是compile,即使不指定默认也是compile
使用exclusions进行排除,如:
com.mqf.maven
Hello
0.0.1-SNAPSHOT
compile
commons-logging
commons-logging
主要从对主程序是否有效、对测试程序是否有效、是否参与打包与部署三个方面对比以上三种依赖范围:
optional表示是否会传递依赖,有两个可填值(假如不声明optional标签,默认就是false):
特点:
什么时候将optional设置为true?
谁用谁引入
多个子工程中依赖同样的jar包,但是采用test范围;由于test范围没有传递性;所以,每一个工程都需要对test范围的jar包进行单独依赖;
而如果希望修改多个工程中所依赖test范围的jar包版本,那么,一个一个项目去修改太麻烦,这时可以应用继承解决。
pom
项目的打包类型:pom、jar、war
packing默认是jar类型,
pom ---------> 父类型都为pom类型
jar ---------> 普通项目打jar包,一般普通项目设置jar
war ---------> web项目一般都是打war包,web项目的话设置war
pom
junit
junit
4.0
test
com.mqf.maven
MavenParent
0.0.1-SNAPSHOT
../MavenParent/pom.xml
junit
junit
Maven 实际上是一个依赖插件执行的框架
,它执行的每个任务实际上都由插件完成的。使用Maven打出来的包并不包含任何 Maven 插件,它们以独立构件的形式存在, 只有在 Maven 需要使用某个插件时,才会去仓库中下载。
如下表所示,Maven 提供了如下 2 种类型的插件:
插件目标: 对于 Maven 插件而言,为了提高代码的复用性,通常一个 Maven 插件能够实现多个功能,每一个功能都是一个插件目标,即 Maven 插件是插件目标的集合。我们可以把插件理解为一个类,而插件目标是类中的方法,调用插件目标就能实现对应的功能。
使用的两种方式:
为了完成某个具体的构建任务,Maven 生命周期的阶段需要和 Maven 插件的目标相互绑定。例如,代码编译任务对应了default 生命周期的 compile 阶段,而 maven-compiler-plugin 插件的 compile 目标能够完成这个任务,因此将它们进行绑定就能达到代码编译的目的。
Maven 默认为一些核心的生命周期阶段绑定了插件目标,当用户调用这些阶段时,对应的插件目标就会自动执行相应的任务。
表中,default 生命周期中只列出了绑定了插件目标的阶段,它还有很多其他的阶段,但这些阶段默认没有绑定任何插件目标,因此它们也没有任何实际的行为。
像这些内置绑定的插件我们也可以在项目当中去显示的声明然后修改配置,这时候内置绑定插件的默认配置将会被覆盖!
除了内置绑定之外,用户也可以自己选择将某个插件目标绑定到 Maven 生命周期的某个阶段上,这种绑定方式就是自定义绑定。自定义绑定能够让 Maven 在构建过程中执行更多更丰富的任务。
例如,我们想要在 clean 生命周期的 clean 阶段中显示自定义文本信息,则只需要在项目的 POM 中 ,通过 build 元素的子元素 plugins,将 maven-antrun-plugin插件的run 目标绑定到 clean 阶段上,并使用该插件输出自定义文本信息即可。
org.apache.maven.plugins
maven-antrun-plugin
3.0.0
custom clean
clean
run
以上配置中除了插件的坐标信息之外,还通过 executions 元素定义了一些执行配置。executions 下的每一个 executin 子元素都可以用来配置执行一个任务。execution 下各个元素含义如下:
当插件目标绑定到生命周期的不同阶段时,其执行顺序由生命周期阶段的先后顺序决定。如果多个目标绑定到同一个生命周期阶段,其执行顺序与插件声明顺序一致,先声明的先执行,后声明的后执行。
官网:https://maven.apache.org/plugins/index.html
参考:
https://blog.51cto.com/u_6346066/7000656
https://zhuanlan.zhihu.com/p/596857284