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:编译、测试和运行。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于