转载:https://my.oschina.net/u/814431/blog/355105
POM是什么?
1、像Make的Makefile、Ant的build.xml一样,Maven项目的核心是pom.xml
2、POM (Project Object Model, 项目对象模型) 定义了项目的基本信息,用于描述项目如何构建,声明项目依赖等等
如何编写一个Hello World的POM?
新建一个名为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/maven/-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.juvenxu.mvnbook</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Maven Hello World Project</name>
</project>
对楼上的配置进行解释
1、代码的第一行是XML头,指定了该xml文档的版本和编码方式
2、紧接着的project元素,project是所有pom.xml的根元素,它还声明了一些POM相关的命名空间及xsd元素(虽然这些属性不是必须的,但使用这些属性能够让第三方工具,如IDE中的XML编辑器,帮助我们快速编辑POM)
3、根元素下的第一个子元素modelVersion指定了当前POM模型的版本,对于Maven2及Maven3来说,它只能是4.0.0
4、最重要的groupId、artifactId和version,这三个元素定义了一个项目基本的坐标,在Maven的世界,任何的jar、pom或者war都是以基于这些基本的坐标进行区分的
groupId是什么意思?
groupId定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联,比如在googlecode上建立了一个名为myapp的项目,那么groupId就应该是com.googlecode.myapp
artifactId是什么意思?
artifactId用于定义该项目下的某个模块,比如myapp-util、myapp-domain、myapp-web等
version是什么意思?
version指定了Hello World项目当前的版本——1.0.SNAPSHOT
SNAPSHOT是什么意思?
SNAPSHOT意为快照,说明该项目还处于开发中,是不稳定的版本。随着项目的发展,version会不断更新,如升级为1.0、1.1-SNAPSHOT、1.1、2.0等
为什么要区分发布版和快照版呢?
考虑这样一种场景,小张在开发模块A的2.1版本,该版本还未正式发布,与模块A一同开发的还有模块B,它由小张的同事季MM开发,B的功能依赖于A。在开发过程中,小张需要经常将自己最新的构建输出,交给季MM,供她开发和测试调试,问题是,这个工作如何进行呢?
方案一:
让季MM自己签出模块A的源码进行构建。这种方法能够确保季MM得到模块A的最新构建,不过她不得不去构建模块A。多了一些版本控制和Maven操作还不算,当构件失败的时候,她会是一头雾水,最后不得不找小张解决。显然,这种方式是低效的
方案二:
重复部署模块A的2.1版本供季MM下载。虽然小张能够保证仓库中的构件是最新的,但对于Maven来说,同样的版本和同样的坐标就意味着同样的构件。因此,如果季MM在本机的本地仓库包含了模块A的2.1版本构件,Maven就不会再对照远程仓库进行更新。除非她每次执行Maven命令之前,清除本地仓库,但这种要求手工干预的做法显然也是不可取的
方案三:
不停更新版本2.1.1、2.1.2、2.1.3 ... ... 首先,小张和季MM两人都需要频繁地更改POM,如果有更多的模块依赖于模块A,就会涉及更多的POM更改;其次,大量的版本其实仅仅包含了微小的差异,有时候是对版本号的滥用
那么如何解决上述问题?
Maven的快照版本机制就是为了解决上述问题的,在该例中,小张只需要将模块A的版本设定为2.1-SNAPSHOT,然后发布到私服中,在发布的过程中,Maven会自动为构件打上时间戳。比如2.1-20091214.221414-13就表示2009年12月14日22点14分14秒的第13次快照。有了该时间戳,Maven就能随时找到仓库中该构件2.1-SNAPSHOT版本最新的文件,这时,季MM配置对于模块A的2.1-SNAPSHOT版本的依赖,当她构建模块B的时候,Maven会自动从仓库中检查模块A的2.1-SNAPSHOT的最新构件。当发现有更新时,便进行下载。默认情况下,Maven每天检查一次更新 (由仓库配置的updatePolicy控制),用户也可以使用命令行-U参数强制让Maven检查更新,如mvn clean install -U
什么时候变成发布版本,为什么发布版本稳定,快照版本不稳定?
当项目经过完善的测试后需要发布的时候,就应该将快照版本更改为发布版本
例如,将2.1-SNAPSHOT更改为2.1,表示该版本已经稳定,且只对应了唯一的构件,相比之下2.1-SNAPSHOT往往对应了大量的带有不同时间戳的构件,这也决定了其不稳定性
最后的是name是什么意思?
最后的name元素声明了一个对于用户更为友好的项目名称,虽然这不是必须的,但还是推荐为每个POM声明name,以方便信息交流
Maven中的项目主代码和测试代码分别是指?
1、项目的主代码会被打包到最终构建中(如jar)
2、项目的测试代码只在运行测试时用到,不会被打包
3、默认情况下,Maven假设项目主代码位于src/main/java目录,测试代码位于src/test/java
关于Java代码有两点需要注意
1、应该把项目主代码放到src/main/java目录下(遵循Maven的约定),而无需额外的配置,Maven会自动搜寻该目录找到项目主代码
2、该Java类的包名是com.juvenxu.mvnbook.helloworld,这与之前在POM中定义的groupId和artifactId相吻合,一般来说,项目中Java类的包都应该基于项目的groupId和artifactId,这样更加清晰、更加符合逻辑,也方便搜索构件或者Java类
scope依赖范围是指?
1、若依赖范围为test表示该依赖只对测试有效,换句话说,测试代码中import JUnit代码是没问题的,但是如果在主代码中用import JUnit代码,就会造成编译错误。
2、若不声明依赖范围,那么默认值就是compile,表示该依赖对主代码和测试代码都有效
一个依赖声明可以包含如下元素
<project>
...
<dependencies>
<dependency>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<type>...</type>
<scope>...</scope>
<optional>...</optional>
<exclusions>
<exclustion>
...
</exclustion>
...
</exclusions>
</dependency>
...
</dependencies>
...
</project>
project元素?
包含一个dependencies
dependencies元素?
包含多个dependency元素,以声明一个或多个项目的依赖
每个dependency元素,可以包含的元素有?
1、groupId、artifactId和version,依赖的基本坐标,Maven根据坐标才能找到需要的依赖
2、type,依赖的类型,对应于项目坐标定义的packaging,大部分情况下,该元素不必声明,默认为jar
3、scope,依赖的范围
4、optional,标记依赖是否可选
5、exclusions:用来排除传递性依赖