Hello,Maven
对于 Maven 的接触已经有很长的一段时间了,但是并没有做过系统的笔记,写这篇博文备忘一下。
Maven 是什么
Maven 与 Composer 一样,是一个资源依赖包的管理工具。
更官方一点,它是一个基于 POM(项目对象模型),可以通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。
Maven 下载与配置
下载
请直接去 Maven 的官方站点下载源码
配置
这里我们假设 Maven 的目录位于/usr/local/maven(附:类 Unix 系统),并且您的系统已经具有 Java 环境。
那么在执行如下操作:
cd ~
vim .bash_profile
.bash_profile 下新增如下两行代码:
export M2_HOME=/usr/local/maven3.3.9/
export PATH=/usr/local/maven3.3.9/bin/:$PATH
再执行
source .bash_profile
测试
mvn -v
如果看见下列信息:
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T00:41:47+08:00)
Maven home: /usr/local/maven3.3.9
Java version: 1.8.0_112, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/jre
Default locale: zh_CN, platform encoding: UTF-8
那就说明您对 Maven 的配置已经完成了。
OS name: "mac os x", version: "10.11.6", arch: "x86_64", family: "mac"
案例
源码
源码请看我的项目 java-core-learn
目录结构
--src
--main
--java(在这个目录下写java代码)
--org
--javacore
--base
--具体java文件
--resources(资源文件)
--test
--base
--具体java文件
maven 配置文件 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>org.javacore</groupId>
<artifactId>java-core-learn</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>java core learning example</name>
<url>http://www.liumapp.com<url>
<description>java core learning example</description>
<packaging>war</packaging>
<developers>
<developer>
<name>liumapp</name>
</developer>
</developers>
<properties>
<google-collections.version>1.0</google-collections.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>${google-collections.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
pom.xml 分析
<xml>标签、<modelVersion>标签和<project>标签是pom的固定结构,我们不需要进行变化。
<groupId>的值就是项目的包名,一般而言,都是按照“组织名+公司网址的反写+项目名”这样的格式来填写,比如说我的网址liumapp.com,我要创建一个helloworld项目,那么包名就应该是com.liumapp.helloworld
<artifactId>的值是模块名,一般使用项目名称+模块名进行标识
<version>表示版本号,比如0.0.1snapshot,第一个0表示大版本号,第二个0表示分支版本号,第三个0表示小版本号,snapshot表示快照版本、alpha表示内侧版本、beta表示公测版本、Release表示稳定版本、GA表示正式发布版本。
<packaging>打包方式,默认是jar(不写这个标签的时候打包成jar),可以使用war、zip、pom等等。
<dependencies>项目的依赖,经常使用到。<dependency>下面有一个<scope></scope>,它表示依赖的范围。比如<scope>test</scope>,那么就说明这个依赖只在测试的范围内有用,超出这个范围去使用就会报错。scope标签的值一共有六种,分别是:compile、provided、runtime、test、system、import。
compile是默认的节点,它表示编译测试和运行都有效。
provided是在测试和编译的时候有效。比如说Servlet的API,在测试和编译的时候有效,但如果在运行的时候,就会和tomcat的servlet发生冲突。
runtime表示在测试和运行时有效。比如jdbc的驱动。
test表示只在测试的时候有效。比如junit
system表示编译和测试时有效,但有很大的不可移植性,只能本地使用。
import表示导入的范围,它只使用在dependencyManagement中,表示从其他的pom中导入dependency的配置。
<dependency>下面还有一个<optional>true/false<optional>默认为false,表示设置依赖是否可选。如果为false,表示这个依赖是可以继承的,如果为true,则这个子项目必须显示引入该依赖。
<dependency>下面还有一个<exclusions>,它表示一个排除依赖传递的列表。比如说Ajar包依赖Bjar包,Bjar包依赖Cjar包,那么C对于A来说,就是一个传递依赖,如果A不想依赖C,就可以在这里面进行声明。排除对C的依赖关系。
这里我很喜欢别人举的一个例子来解释依赖传递,在古惑仔里面,山鸡跟楠哥混,楠哥跟B哥混,所以山鸡就间接的跟B哥混,所以山鸡跟B哥之间的关系,就是一个依赖传递的关系。那如果有一天,山鸡跟楠哥表忠心,说我只听你的,不听B哥的,那么山鸡这个项目里,在依赖楠哥的时候,还要再加一条对B哥的排除依赖。
<dependencyManagement></dependencyManagement>表示依赖的管理。这个标签里面也是写dependencies和dependency,但是这里面的依赖并不会被实际的引用。
<build>为构建行为提供支持,比如说使用maven的相关插件。
<parent>通常用于子模块中对父模块pom.xml的继承
<modules>定义多个模块然后一起编译。
<name>表示项目的描述名,一般用于在生成项目文档的时候使用。
<url>项目的地址。
<description>项目描述
<developers>项目开发人员列表
<license>
<organization>
运行
进入项目目录后,运行
mvn compile
maven 会自动下载依赖的项目,并且完成编译。
再运行
mvn test
maven 会自动的运行我们写在 test 目录下的测试用例。
再运行
mvn package
maven 会自动对我们的项目进行编译后的打包
maven 生成的文件
运行完上述说的命令后,项目根目录下应该会出现如下所示的目录
--target
--classes //编译后的文件
--maven-status
--surefire-reports//存放测试报告
--test-classes
Maven 中的坐标和仓库
坐标与构件
构件:maven 中,任何一个依赖,插件,项目构建的输出都可以被称之为构件。
构件通过坐标作为其唯一标识。
而坐标呢,则是由 pom.xml 文件中的 groupId 、artifactId 和 version 来组成。
仓库
仓库分为本地仓库和远程仓库。
maven 在安装依赖之前,会先去本地的 maven 仓库中查找是否有相同的依赖,如果有,则不会去网上下载,直接使用本地的依赖,如果没有,再去网上进行下载。这里的网上,则是指的 maven 的远程仓库。
一般而言,maven 默认的会给我们一个远程仓库地址:https://repo.maven.apache.org/maven2
这个地址我们可以在 maven 项目源码里面的 org\apache\maven\model\pom-4.0.0.xml 这个文件里面找到。(被命名为:Central Repository,中央仓库)
镜像仓库
maven 的中央仓库位置在国外,可能有些时候访问无法成功,这个时候我们就需要使用 maven 在国内的镜像仓库。
使用方法
进入本地 maven 项目目录,进入 conf 目录,打开 settings.xml 文件
大概在 146 行左右的样子,找到 mirrors 标签。添加如下代码:
<mirror>
<id>maven.net.cn</id>
<mirrorOf>central</mirrorOf>
<name>central mirror in china</name>
<url>http://maven.net.cn/content/groups/public/</url>
</mirror>
保存后退出即可。
当然国内的话,还是阿里云的要快一点,所以我们可以使用这个地址:http://maven.aliyun.com/nexus/content/groups/public/
更改仓库位置
默认位置
默认情况下,maven 安装的依赖都位于如下地址:
cd ~/.m2/repository
更改方法
依然在 settings.xml 文件中,我们找到第 55 行左右的标签,然后输入新的地址即可。
<localRepository>/path/to/repository</localRepository>
Maven 的生命周期
完整的项目构建过程包括:清理、编译、测试、打包、集成测试、验证、部署。
Maven 生命周期:
clean 清理项目
pre-clean 执行清理前的工作
clean 清理上一次构建生成的所有文件
post-clean 执行清理后的文件
default 构建项目(最核心的一部分)
compile、test、package、install等等。
site 生成项目站点
pre-site 在生成项目站点前要完成的工作
site 生成项目的站点文档
post-site 在生成项目站点后要完成的工作
site-deploy 发布生成的站点到服务器上
在这几个clean、compile、test、package、install命令中,当我们运行package的时候,clean、compile、test将会在在package之前依次运行。
Maven 的插件
官方插件列表:http://maven.apache.org/plugins/
对 source 插件的使用
source 插件:将项目的源码进行打包
在 pom.xml 文件的 project 节点内添加如下代码:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
上面代码中的 executions 节点,用来绑定插件 source 到 maven 的 package 生命周期中。
goal 目标节点的内容,可以在插件详情里面查看。
接下来运行 package 即可。
依赖冲突
比如说,我现在的项目为 A,A 依赖 B 项目,A 也依赖 C 项目,B 项目和 C 项目都依赖一个 D 项目,但是呢,B 项目依赖 D 的 1.0 版本,而 C 项目依赖 D 的 2.0 版本,那这个时候怎么办呢。
短路优先
在 maven 中,首先要遵循短路优先原则。意思就是,优先解析路径短的版本。比如 A 依赖 B,B 依赖 C,C 依赖 X(jar,2.0 版本),然后又有 A 依赖 D,D 依赖 X(jar,1.0 版本),那么最后 maven 会优先解析 X 的 1.0 版本。
先声明先优先
如果路径长度相同,则原先声明,先解析谁。
聚合和继承
聚合
在 maven 中,如果想将多个项目进行 install,将其安装到本地仓库中,必须对其依次执行 install 操作。maven 中有一种方式,可以将其放到一起运行,这种方式称之为聚合。
具体使用方法:
-
首先我们需要新建一个项目,然后将项目的打包方式修改为 pom,也就是把 packaging 元素的值设定为 pom
-
然后在 pom.xml 文件中,添加如下代码:
<modules> <module>/path/to/your/moduleA</module> <module>/path/to/your/moduleB</module> <module>/path/to/your/moduleC</module> </modules>
-
再在这个项目的目录下运行 mvn install 即可。
继承
基本上不管哪一个 maven 项目,都会用到 junit,而且每一个项目的 pom.xml 文件,都会对其进行配置。这个时候就会出现很多重复的配置代码。
所以在 maven 中,我们可以像 java 一样,将共用的部分,写成一个父类。
具体使用方法:
-
新建一个 maven 项目(假设命名为 parent),packaging 改为 pom,将要写入的依赖,写在 dependencyManagement 中。如下所示:
<properties> <junit.version>4.12</junit.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> <version>${junit.version}</version> </dependency> </dependencies> </dependencyManagement>
-
在其他的 maven 项目中,去继承 parent。代码如下所示:
在 pom.xml 文件中:<parent> <groupId>parent的groupId</groupId> <artifactId>parent的artifactId</artifactId>= <version>parent的version</version> </parent> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> </dependencies>
如上所示,继承 parent 之后,再引用 junit,已经不需要进行过多的配置了,只需要定义它的坐标即可。
常用命令
mvn -v 查看maven版本
-compile 编译整个项目
-test 执行test下面的测试代码
-package 打包
-clean 删除编译后的字节码文件和测试报告等等,也就是删除target
-install 安装jar包到本地仓库中
在使用命令的时候,可以多个命令按照顺序使用,如:
mvn clean compile
就表示先 clean,再 compile
自动创建目录骨架
使用 archetype 插件,用于创建符合 maven 规定的目录骨架,具体代码如下:
mvn archetype:generate
如果是第一次运行的话,maven 会自动的下载相关依赖,同时我们还要进行版本的选择。一般选择第六个就可以了。
之后,会要求我们输入 groupId,这里按照自己想要的项目包名输入。
然后是 artifactId,输入项目名即可。
然后是 version,版本号,一般第一次执行都是 1.0.0SNAPSHOT
再是 package,包名,输入项目包名再加一个-service 即可。
最后进行确认整个项目的骨架就自动创建好了。
当然我们也可以直接使用一条命令完成整个过程:
mvn archetype:generate -DgroupId=yourGroupId -DartifactId=yourArtifactId -Dversion=1.0.0SNAPSHOT -Dpackage=yourPackage
利用 maven 发布 web 项目
相关源码可以看我的项目 jsp-basic
-
利用插件创建项目
-
添加对 servlet 的依赖,具体坐标请前往官网查找(很多依赖我们都需要在官网上去找)。这里推荐:http://mvnrepository.com/
-
设定 servlet 的依赖 scope 值为 provided。
-
packaging 设定为 war
-
添加 maven 的 jetty 插件。
-
执行 mvn compiler,接下来就能够在浏览器成功访问到项目。
-
如果要使用 tomcat 作为 web 容器,那么就是用 tomcat 对 maven 的插件来取代 jetty 即可。
注意事项
请注意,maven 在安装依赖之前,会先去本地的 maven 仓库中查找是否有相同的依赖,如果有,则不会去网上下载,直接使用本地的依赖,如果没有,再去网上进行下载。
另外需要注意的是,如果我们有两个项目 A 和项目 B,项目 B 需要引用项目 A 的类的话,通过 maven,我们只需要在项目 A 中执行命令 mvn -install ,这样将会把 A 保存在本地仓库中,接下来再到项目 B 的 pom.xml 文件中添加对 A 的 dependency,再执行 compaile,maven 就能够自动的下载 A 的依赖。
在 maven 中,有三种 classpath:编译、测试和运行。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于