写在前面:
Maven和之前的Git都是之前在学校自己通过网上文章和视频对照着学习过。对它们有一定了解但不是特别清楚它们在项目当中的作用和具体的使用方法,最近项目中用到了正好可以把理论的东西和实战相结合,这样理解起来更加得心应手。开始吧。
导言:生产环境下开发不再是一个项目一个工程,而是每一个模块创建一个工程,而多个模块整合在一起就需要使用到像 Maven 这样的构建工具。
一、Maven 简介
1.Maven是一款服务于Java平台的自动化构建工具。
Mark---->Ant---->Maven---->Gradle自动化构建工具种类繁多Maven为王
2.什么是构建
①概念:以“Java源文件”、“框架配置文件”、“JSP”、“HTML”等资源为“原材料”,去生产一个可以运行的项目的过程。
编译--->部署--->搭建
②编译:Java源文件[User.java]-->编译-->Class字节码文件[User.class] -->交给JVM
去执行
③部署:当我们需要通过浏览器访问 Java 程序时就必须将包含 Java 程序的 Web 工程编译的结果“拿”到服务器上的指定目录下,并启动服务器才行。这个“拿”的过程我们叫部署。我们可以将未编译的 Web 工程比喻为一只生的鸡,编译好的 Web 工程是一只煮熟的鸡,编译部署的过程就是将鸡炖熟。
生的鸡--->处理--->熟的鸡
动态Web工程--->编译、部署--->编译结果
开发过程中,所有的路径或配置文件中配置的类路径等都是以编译结果的目录结构为标准的。
那么项目构建的全过程中都包含哪些环节呢?
二、构建过程的几个主要环节
①清理:删除以前的编译结果,为重新编译做好准备。
②编译:将 Java 源程序编译为字节码文件。
③测试:自动测试,自动调用junit程序
④报告:测试程序执行的结果。
⑤打包:Java 工程对应 jar 包,Web工程对应 war 包,父工程对应pom包。
⑥安装:Maven特定的概念-----将打包得到的文件复制到“仓库”中的指定位置。
⑦部署:将打包的结果部署到远程仓库或将 war 包部署到服务器上运行。
Maven 的意义就体现出来了,它可以自动的从构建过程的起点一直执行到终点。
三、安装Maven核心程序
①检查JAVA_HOME环境变量
C:\Windows\System32>echo %JAVA_HOME%
D:\DevInstall\jdk1.7.0_07
② 解压Maven的核心程序
将apache-maven-3.2.2-bin.zip解压到一个非中文无空格的目录下。例如D:\DevInstall\apache-maven-3.2.2
③配置环境变量
M2_HOME D:\DevInstall\apache-maven-3.2.2
path D:\DevInstall\apache-maven-3.2.2\bin
④查看Maven版本信息验证安装是否正确
C:\Windows\System32>mvn -v
Apache Maven 3.2.2 (45f7c06d68e745d05611f7fd14efb6594181933e; 2014-06-17T21:51:42+08:00)
Maven home: D:\DevInstall\apache-maven-3.2.2\bin\..
Java version: 1.7.0_07, vendor: Oracle Corporation
Java home: D:\DevInstall\jdk1.7.0_07\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows"
Ps: 关于联网问题
四、Maven 核心概念
Maven 能够实现自动化构建是和它的内部原理分不开的,这里我们从 Maven 的九个核心概念入手,看看 Maven 是如何实现自动化构建的。
POM
含义:Project Object Model:项目对象模型。
DOM(Document Object Model)文档对象模型
pom.xml文件对于Maven工程是核心配置文件,与构建过程相关的一切设置都在这个文件中进行配置。重要程度相当于web.xml对于Web工程。
2. 约定的目录结构
约定的目录结构对于 Maven 实现自动化构建而言是必不可少的一环,就拿自动编译来说,Maven 必须能找到 Java 源文件,下一步才能编译,而编译之后也必须有一个准确的位置保持编译得到的字节码文件。
Hello
|---src
|---|---main
|---|---|---java
|---|---|---resources
|---|---test
|---|---|---java
|---|---|---resources
|---pom.xml
为什么要遵守约定的目录结构呢?
Maven要负责我们这个项目的自动化构建,以编译为例,Maven要想自动进行编译,那么它必须知道Java源文件保存在哪里。我们在开发中如果需要让第三方工具或框架知道我们自己创建的资源在哪,那么基本上就是两种方式:
①通过配置的形式明确告诉它
<param-value>classpath:spring-context.xml</param-value>
②基于第三方工具或框架的约定(Maven对工程目录结构的要求就属于这一种)
Log4j.properties
Log4j.xml
现在 JavaEE 开发领域普遍认同一个观点:约定>配置>编码。意思就是能用配置解决的问题就不编码,能基于约定的就不进行配置。而 Maven 正是因为指定了特定文件保存的目录才能够对我们的 Java 工程进行自动化构建。
3. 坐标
几何中的坐标
在一个平面中使用 x、y 两个向量可以唯一的确定平面中的一个点。
在空间中使用 x、y、z 三个向量可以唯一的确定空间中的一个点。
Maven 的坐标
使用下面三个向量在仓库中唯一定位一个Maven工程
groupid:公司或组织的域名倒序+当前项目名称
artifactId:当前项目的模块名称
version:当前模块的版本
<groupId>com.atguigu.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
如何通过坐标到仓库中查找 jar 包?
将 gav 三个向量连起来, 以连起来的字符串作为目录结构到仓库中查找
com/atguigu/maven/Hello/0.0.1-SNAPSHOT/Hello-0.0.1-SNAPSHOT.jar
4. 依赖管理
Maven解析依赖信息时会到本地仓库中查找被依赖的jar包
对于我们自己开发的Maven工程,使用mvn install命令安装后就可以进入仓库。
依赖的目的是什么?
当 A jar 包用到了 B jar 包中的某些类时,A 就对 B 产生了依赖,这是概念上的描述。那么如何在项目中以依赖的方式引入一个我们需要的 jar 包呢?答案非常简单,就是使用 dependency 标签指定被依赖 jar 包的坐标就可以了。
<dependency>
<groupId>com.atguigu.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
依赖的范围
大家注意到上面的依赖信息中除了目标 jar 包的坐标还有一个 scope 设置,这是依赖的范围。依赖的范围有几个可选值,我们用得到的是:compile、test、provided 三个。
从项目结构角度理解 compile 和 test 的区别
从开发和运行这两个不同阶段理解 compile 和 provided 的区别
有效性总结
依赖的传递性
A 依赖 B,B 依赖 C,A 能否使用 C 呢?那要看 B 依赖 C 的范围是不是 compile,如果是则可用,否则不可用。
依赖的排除
如果我们在当前工程中引入了一个依赖是 A,而 A 又依赖了 B,那么 Maven 会自动将 A 依赖的 B 引入当前工程,但是个别情况下 B 有可能是一个不稳定版,或对当前工程有不良影响。这时我们可以在引入 A 的时候将 B 排除。
<dependency>
<groupId>com.atguigu.maven</groupId>
<artifactId>HelloFriend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>jar</type>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
统一管理所依赖 jar 包的版本
对同一个框架的一组 jar 包最好使用相同的版本。为了方便升级框架,可以将 jar 包的版本信息统一提取出来。
√统一声明版本号
<properties>
<atguigu.spring.version>4.1.1.RELEASE</atguigu.spring.version>
</properties>
其中 atguigu.spring.version 部分是自定义标签。
√引用前面声明的版本号(在需要统一版本的位置,使用${自定义标签名}引用声明的版本号)
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${atguigu.spring.version}</version>
</dependency>
……
</dependencies>
√其他用法 让整个项目统一字符集编码
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
依赖的原则:解决 jar 包冲突
√路径最短者优先
√路径相同时先声明者优先(这里“声明”的先后顺序指的是 dependency 标签配置的先后顺序)
5.仓库管理
本地仓库:为当前本机电脑上的所有 Maven 工程服务。
远程仓库
√私服:架设在当前局域网环境下,为当前局域网范围内的所有 Maven 工程服务。
√中央仓库:架设在 Internet 上,为全世界所有 Maven 工程服务。
√中央仓库的镜像:架设在各个大洲,为中央仓库分担流量。减轻中央仓库的压力,同时更快的响应用户请求
maven中的仓库分为两种
snapshot快照仓库
snapshot快照仓库用于保存开发过程中的不稳定版本。只需要在pom文件中在该模块的版本号后加上-SNAPSHOT即可(注意这里必须是大写)
release发布仓库
release正式仓库则是用来保存稳定的发行版本。
两者区别
如果是快照版本,那么在mvn deploy时会自动发布到快照版本库中,而使用快照版本的模块,在不更改版本号的情况下,直接编译打包时,maven会自动从镜像服务器上下载最新的快照版本。
如果是正式发布版本,那么在mvn deploy时会自动发布到正式版本库中,而使用正式版本的模块,在不更改版本号的情况下,编译打包时如果本地已经存在该版本的模块则不会主动去镜像服务器上下载。
在distributionManagement段中配置的是snapshot快照库和release发布库的地址
server的id必须和pom文件中的distributionManagement对应仓库的id保持一致,maven在处理发布时会根据id查找用户名称和密码进行登录和文件的上传发布。 参考地址: https://blog.csdn.net/aitangyong/article/details/5333209 |
6.生命周期
什么是 Maven 的生命周期?
Maven 生命周期定义了各个构建环节的执行顺序,有了这个清单,Maven 就可以自动化的执行构建命令了
三套相互独立的生命周期
CleanLifecycle 在进行真正的构建之前进行一些清理工作。
Default Lifecycle 构建的核心部分,编译,测试,打包,安装,部署等等。
Site Lifecycle 生成项目报告,站点,发布站点。
它们是相互独立的,你可以仅仅调用 clean 来清理工作目录,仅仅调用 site 来生成站点。当然你也可以直接运行 mvn clean install site 运行所有这三套生命周期。每套生命周期都由一组阶段(Phase)组成,我们平时在命令行输入的命令总会对应于一个特定的阶段。比如,运行 mvn clean,这个 clean 是 Clean 生命周期的一个阶段。有 Clean 生命周期,也有 clean 阶段。
生命周期与自动化构建
运行任何一个阶段的时候,它前面的所有阶段都会被运行,例如我们运行 mvn install 的时候,代码会被编译,测试,打包。这就是 Maven 为什么能够自动执行构建过程的各个环节的原因。此外,Maven 的插件机制是完全依赖 Maven 的生命周期的,因此理解生命周期至关重要。
7.插件和目标
●Maven 的核心仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的。
●每个插件都能实现多个功能,每个功能(compile,pre-clean)就是一个插件目标。
●Maven的生命周期与插件目标相互绑定,以完成某个具体的构建任务。
例如:compile 就是插件 maven-compiler-plugin 的一个目标;pre-clean 是插件 maven-clean-plugin 的一个目标。
8.继承
为什么需要继承机制?
由于非 compile 范围的依赖信息是不能在“依赖链”中传递的,所以有需要的工程只能单独配置。
问题:
Hello依赖junit:4.0
HelloFriend依赖junit:4.0
MakeFriend依赖junit:4.9
解决思路:将junit依赖统一提取到“父”工程中,在子工程中声明junit依赖时不指定版本,以父工程统一设定的为准。同时也便于修改。
操作步骤:
①创建一个Maven工程作为父工程。注意:打包的方式pom
②在子工程中声明对父工程的引用。此时如果子工程的 groupId 和 version 如果和父工程重复则可以删除。
③将子工程的坐标与父工程坐标中重复的内容删除
④在父工程中统一管理junit的依赖。用 dependencyManagement 标签括起来。
⑤在子项目中重新指定需要的依赖,删除范围和版本号。
9.聚合
为什么要使用聚合?
将多个工程拆分为模块后,需要手动逐个安装到仓库后依赖才能够生效。修改源码后也需要逐个手动进行 clean 操作。而使用了聚合之后就可以批量进行Maven 工程的安装、清理工作。
如何配置聚合?
在总的聚合工程中使用 modules/module 标签组合,指定模块工程的相对路径即可。
<modules>
<!--指定各个子工程的相对路径-->
<module>../Hello</module>
<module>../HelloFriend</module>
<module>../MakeFriends</module>
</modules>
五、Maven 酷站
我们可以到 http://mvnrepository.com/搜索需要的 jar 包的依赖信息。
六、Idea中部署Maven
=====暂时先到这里了 ヾ(•ω•`)o====
点“在看”你懂得