掌握Maven_1
来源:互联网 发布:大连住电软件 编辑:程序博客网 时间:2024/06/15 09:38
Maven 主要服务于基于Java平台的项目构建、依赖管理和项目信息管理。
一、安装和配置
maven中央仓库:repo1.maven.org
http://repo1.maven.org/maven2/
1、maven的安装:
略
2、maven的安装目录分析:
maven安装目录下的文件结构:
bin:
包含mvn运行的脚本。脚本文件:mvn与mvnDebug的区别是mvnDebug多了一条MAVEN_DEBUG_OPTS配置,其作用就是运行Maven时开启debug,以便调试Maven本身;
m2.conf是classworlds的配置文件。
boot:
该目录只包含一个文件,以maven 3.0为例,该文件为plexus-classworlds-2.2.3.jar ,是一个类加载器框架,Maven使用该框架加载自己的类库。
conf:
该目录包含的settings.xml。用来在机器上全局地定制Maven的行为。(用户目录/.m2/下的settings用来在用户范围内定制maven的行为)
lib:
该目录包含了所有Maven运行时需要的Java类库
LICENSE.txt:记录了Maven使用的软件许可证
NOTICE.txt:记录了Maven包含的第三方软件
README.txt:包含了Maven的简要介绍,包括安装需求及如何安装的简要指令等。
3、maven配置:
mvn help:system 命令会打印所有的Java系统属性和环境变量
设置HTTP代理:
有些公司处于安全考虑,需要通过安全认证的代理访问互联网,这种情况下,就需要Maven配置HTTP代理,才能让它访问外部仓库。
检查自己的主机是否能访问公共的Maven中央仓库:ping repo1.maven.org
检查代理服务器是否畅通:telnet 服务器地址 端口
编辑settings.xml文件,在<proxies>节点下添加<proxy>元素配置。
注意:proxies下可以有多个proxy元素,当有多个时,第一个被激活的proxy会生效,另外当代理服务需要认证时,就需要配置username和password元素,nonProxyHost元素指定哪些主机名不需要代理(支持通配符)
4、安装m2eclipse:
略
5、Maven安装最佳实践:
(1)、设置MAVEN_OPTS环境变量
设置MAVEN_OPTS 的值为 -Xms128m -Xmx512m
原因是Java默认的最大可用内存往往不能够满足Maven运行的需要,如果没有该配置,则很容易得到java.lang.OutOfMemeoryError。
(2)、配置用户范围settings.xml
Maven用户可以选择配置安装目录下的conf/settings.xml或用户目录/.m2/settings.xml 。前者是全局范围的,整台机器上的所有用户都会受到该配置的影响,而后者是用户范围的,只有当前用户才会受到该配置的影响。
推荐使用用户范围的settings.xml,主要是为了避免无意识地影响到系统中的其他用户。同时也便于Maven升级(因为每次Maven升级,conf/settings.xml文件会被覆盖掉)。
(3)、不要使用IDE内嵌的Maven
无论Eclipse还是NetBeans,当集成Maven时,都会安装上一个内嵌的Maven,这个内嵌的Maven通常会比较新,但带来两个问题:(1)、较新版本的Maven存在很多不稳定因素,容易造成一些难以理解的问题,(2)、除了IDE,也经常使用命令行Maven,如果内嵌版本的Maven与外部安装的Maven版本不一致,容易造成构建行为的不一致。
在Eclipse中,点击Windows->Preferences->Maven->Installation选项,去掉Embedded Maven的勾选,单击Add..按钮,选择Maven安装目录,就可以添加一个外部的Maven.
二、Maven入门
1、POM.xml
Maven项目的核心是pom.xml
POM(Project Object Model, 项目对象模型)定义了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。
在pom.xml中project是pom.xml的根元素;
modelVersion子元素指定了当前POM模型的版本,对于Maven 2及Maven 3 来说,它只能是4.0.0。
在Maven的世界中,任何的jar、pom或者war都是以基于这些基本的坐标进行区分的。
groupId定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联。譬如com.goolecode.myapp。
artifactId定义了当前Maven项目在组中唯一的ID,一般为不同的子项目(模块)分配artifactId,如myapp-util、myapp-domain、myapp-web等。
version指定了项目当前的版本。 例如1.0-SNAPSHOT。SNAPSHOT意为快照,说明该项目还处于开发中,是不稳定的版本。或者是:1.1 、2.0等
name:声明了一个对于用户更为友好的项目名称,(不是必须的,但推荐为每个POM声明name,以方便信息交流)。
2、项目主代码
项目主代码和测试代码不同,项目的主代码会被打包到最终的构件中(如jar),而测试代码只在运行测试时用到,不会被打包。
遵循Maven的约定,maven项目的主代码位于src/main/java目录。
注:当主代码位于src/main/java(即遵循Maven的约定)时,无须额外配置,Maven会自动搜寻该目录找到项目主代码。
3、项目测试代码
项目测试代码与项目主代码应该分别位于独立的目录中。Maven项目中默认的测试代码目录是src/test/java。另外,Java中JUnit是事实上的单元测试标准。如果项目中要使用JUnit,需要在pom.xml中添加<dependency>节点,如下所示:
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> <scope>test</scope> </dependency> </dependencies>
Maven在编译时会首先去本地仓库中查找junit-4.7.jar,如果未找到,就会自动访问中央仓库(http://repo1.maven.org/maven2/),下载需要的文件到本地仓库。
注意:scope元素为依赖范围,若依赖范围为test,则表示该依赖只对测试有效。默认值为compile,表示该依赖对主代码和测试代码都有效。
由于历史原因,Maven的核心插件之一——compiler插件默认只支持编译Java 1.3 ,因此如果需要该插件支持Java 5 ,则需要在pom.xml中<build>节点下的<plugins>节点下添加对应的<plugin>节点,如:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> </plugins> </build>
4、生成可执行的jar
默认打包生成的jar是不能够直接运行的,因为带有main方法的类信息不会添加到manifest中。为了生成可执行的jar文件,需要借助maven-shade-plugin,配置该插件如下:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>1.2.1</version> <executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><transformers><transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><mainClass>com.juvenxu.mvnbook.helloworld.HelloWorld</mainClass></transformer></transformers></configuration></execution> </executions></plugin>
配置完成后,执行package命令,会在target/目录下找到两个jar,其中一个以original开头,表示该jar是原始的jar,不可直接执行,另一个就是可执行的jar。
5、mvn 命令
clean命令:清理输出目录target/
compile命令:编译项目主代码,默认情况下,Maven构建的所有输出都在target/目录下。
test命令:执行测试代码
package命令:打包命令,默认输出目录为:target/
install命令:安装命令,即将打包后的jar、pom安装到Maven本地仓库中,供其他项目使用
注意:执行test之前会先执行compile命令,执行package之前会先执行test命令,执行install之前会执行package命令。
6、使用Archetype生成项目框架
Maven提供了Archetype可以帮助我们快速勾勒出项目框架。使用方法:
如果是Maven 3 ,简单地运行 mvn archetype:generate
如果是Maven 2, 最好运行如下命令:mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-5:generate
此外,也可以开发自己的Archetype,然后在这些项目中使用自定义的Archetype来快速生成项目骨架。
7、m2eclipse简单使用
在m2eclipse中执行Maven构建时,默认的选项中可能没有我们想要执行的Maven命令,比如默认带有mvn test,但我们想执行mvn clean test,我们可以在Maven build以自定义Maven运行命令,在弹出对话框的Goals一项中输入我们想要执行的命令,如clean test,设置一下Name,单击Run即可,并且,下次选择Maven build,或者使用快捷键“Alt + Shift + X, M”快速执行maven构建时,上次的配置直接就能在历史记录中找到。
三、坐标与依赖
1、Maven坐标详解
Maven定义了一组规则:世界上任何一个构件都可以使用Maven坐标唯一标识。
Maven坐标的元素包括:groupId、artifactId、version、packaging、classifier。
groupId:定义当前Maven项目隶属的实际项目。
比如:SpringFramework这一实际项目,其对应的Maven项目会有很多,如spring-core、spring-context等。
artifactId:定义实际项目中的一个Maven项目(模块),推荐的做法是使用实际项目名称作为artifactId的前缀。
比如:artifactId是nexus-indexer,就是使用了实际项目名nexus作为前缀的。
version:定义Maven项目当前所处的版本
packaging:定义Maven项目的打包方式,默认的打包方式为jar。
classifier:用来帮助定义构建输出的一些附属构件。
附属构件与主构件对应,有些项目不仅会输出主构件,例如nexus-indexer-2.0.0.jar,也可能通过一些插件生成nexus-indexer-2.0.0-javadoc.jar、nexus-indexer-2.0.0-sources.jar。这里的javadoc和sources就是两个附属构件的classifier。这样附属构件也就拥有了自己的唯一的坐标。
注意:不能直接定义项目的classifier,因为附属构件不是项目直接默认生成的,而是由附加的插件帮助生成的。
另外,项目构件的文件名是与坐标相对应的。一般的规则为:artifactId-version [-classifier] .packaging
2、依赖的配置
根元素project下的dependencies可以包含一个或者多个dependency元素,以声明一个或者多个项目依赖:
groupId、artifactId、version:依赖的基本坐标
type:依赖的类型,对应于项目坐标定义的packaging,默认值为jar
scope:依赖的范围
optional:标记依赖是否可选
exclusions:用来排除传递依赖
(1)、依赖范围
依赖范围用来控制依赖与三种classpath(编译classpath、测试classpath、运行classpath)的关系。
Maven有以下几种依赖范围:
compile:编译依赖范围。如果没有指定,默认使用该依赖范围,使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。
test:测试依赖范围。使用此依赖范围的maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此类依赖。
provided:已提供依赖范围,使用此依赖范围的maven依赖,对于编译和测试classpath有效,但在运行时无效。
runtime:运行时依赖范围。使用此依赖范围的maven依赖,对于测试和运行classpath有效,但在编译主代码是无效。
system:系统依赖范围。该依赖与三种classpath的关系,和provided依赖范围完全一致。但是,使用system范围的依赖时必须通过systemPath元素显式地指定依赖文件的路径。(此类依赖不是通过Maven仓库解析的,往往与本机系统绑定,可能造成构件的不可移植,因此应该谨慎使用)
import(Maven 2.0.9及以上):导入依赖范围
(2)、传递性依赖
构件A依赖于构件B, 构件B依赖于构件C, 那么构件A与构件C之间就存在传递性依赖。我们可以说:A对于B是第一直接依赖。 B对于C是第二直接依赖。A对于C是传递性依赖。
Maven会解析各个直接依赖的POM,将那些必要的间接依赖以传递性依赖的形式引入到当前的项目中。
依赖范围对传递性依赖的影响:(下图:最左边一列是第一直接依赖范围, 最上面一行是第二直接依赖范围, 中间交叉单元是传递性依赖范围)
(3)、依赖调解
当传递性依赖造成问题时,我们需要清楚该怎样引入传递性依赖(采用哪条路径引入)。这就是依赖调解。
例如:项目A有这样的依赖关系:A->B->C->X(1.0)、A->D->X(2.0),X是A的传递性依赖,但是两条依赖路径上有两个版本的X,那么哪个X会被Maven解析使用呢?这时就需要依赖调解原则。
依赖调解原则:
第一原则:路径最近者优先。即路径短的优先,如上例中X(1.0)的路径长度为3,而X(2.0)的路径长度为2,因此X(2.0)会被解析使用。
第二原则:第一声明者优先。在依赖路径长度相等的前提下,在POM中依赖声明的顺序决定谁被解析,顺序靠前的版本优先。
(4)、可选依赖
如果项目A依赖于项目B,项目B实现了两个特性,其中的特性一依赖于X,特性二依赖于Y,而且这两个特性是互斥的,用户不可能同时使用两个特性。那么就会存在可选依赖:A->B、B->X(可选)、B->Y(可选),这里X、Y是可选依赖,依赖将不会传递。
可选依赖,在dependency节点中的<optional>元素表示这两个依赖时可选依赖:具体形式为:<optional>true</optional>
在理想情况下,不应该使用可选依赖。可以将两个可选的依赖,实现为基于同样groupId,分配不同的artifactId的模块。
(5)、关于依赖的最佳实践
【1】、排除依赖
比如当需要发布一个项目的稳定版本时,发现其存在SNAPSHOT版本的某个传递性依赖。而SNAPSHOT版本不稳定可能影响当前的项目。因此,可以使用排除依赖,来排除掉该SNAPSHOT版本,并使用另一个稳定版本来代替。
具体做法是:在dependency节点下,<exclusions>子节点下添加<exclusion>元素。例如:
<dependency> ...<exclusions><exclusion><groupId>com.juvenxu.mvnbook</groupId><artifactedId>projectt-c</artifactedId></exclusion></exclusions></dependency>
注意:声明exclusion的时候只需要groupId和artifactId,而不需要version元素。因为Maven解析后的依赖中,不可能出现groupId和artifactId相同,但是version不同的两个依赖。
【2】、归类依赖
可能存在这种情况,pom.xml中声明了多个依赖,但是都许多依赖时来自同一个项目的不同模块。因此要求这些依赖的版本都是相同的。当需要将该依赖项目升级到高版本时,就需要所有该项目的模块依赖都要升级。为了方便,可以使用归类依赖。
具体做法:使用Maven属性
例如:
<project><modelVersion>4.0.0</modelVersion><groupId>com.juvenxu.mvnbook.account</groupId><artifactedId>account-email</artifactedId><name>Account Email</name><version>1.0.0-SNAPSHOT</version> <properties><springframework.version>2.5.6</springframework.version></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactedId>spring-core</artifactedId><version>${springframework.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactedId>spring-beans</artifactedId><version>${springframework.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactedId>spring-context</artifactedId><version>${springframework.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactedId>spring-context-support</artifactedId><version>${springframework.version}</version></dependency></dependencies></project>
Maven运行时会将POM中所有的${springframework.version}替换成实际值2.5.6。
【3】、优化依赖
通过mvn命令,可以查看已解析依赖(Resolved Dependency),可以直观地反映项目的依赖情况,使我们可以更好的优化依赖关系。
mvn dependency:list : 查看项目的所有顶层依赖
mvn dependency:tree : 查看项目的依赖树(包括顶层依赖、二层、三层依赖等)
mvn dependency:analyze : 分析当前的项目依赖。
注意:mvn dependency:analyze 命令的结果有两个部分:第一部分:Used undeclared dependencies,指项目中使用到的,但是没有显式声明的依赖。这类依赖意味着潜在的风险,建议显式声明任何项目中直接用到的依赖。 第二部分:Unused declared dependencies,指项目中未使用的,但是显式声明的依赖,对于 这样的依赖,我们不应该简单地直接删除其声明,而应该仔细分析。因为dependency:analyze只会分析编译主代码和测试代码需要用到的依赖,一些执行测试和运行时需要的依赖它就发现不了。
四、仓库
Maven可以在某个位置统一部署所有Maven项目共享的构件,这个统一的位置就是仓库。
1、仓库的布局
Maven仓库是基于简单文件系统存储的,Maven会根据任何一个构件的唯一坐标,定位到其在仓库中的唯一存储路径。
其定位过程是:假设一个构件:groupId = org.testng、artifactId = testng、version=5.8、classifier=jdk15、packaging=jar
** 基于构件的groupId准备路径: 将org.testng 转换成org/testng/ (即将句点分隔符替换成路径分隔符,最后再加一个路径分隔符)
** 基于构件的artifactId准备路径:结果为:org/testng/testng/ (在上一步基础上,加上artifactId,再加路径分隔符)
** 使用版本信息: 结果:org/testng/testng/5.8/
** 依次加上artifactId,构件分隔符连字符,以及version,结果为:org/testng/testng/5.8/testng-5.8
** 如果构件有classifier,就加上构件分隔符和classifier,结果为:org/testng/testng/5.8/testng-5.8-jdk5
** 检查构件的extension,若extension存在,则加上句点分隔符和extension。extension是由项目的packaging决定的:结果:org/testng/testng/5.8/testng-5.8-jdk5.jar
这个结果就是构件在仓库中的实际存储路径。
2、仓库的分类
maven仓库有两类:本地仓库和远程仓库
远程仓库又有如下的种类:中央仓库、私服、其他公开的远程仓库。
本地仓库:
Maven项目所在本机上的仓库。当Maven在执行编译或测试时,如果需要使用依赖文件,它总是基于坐标先使用本地仓库的依赖文件。
默认的本地仓库目录为:用户/.m2/repository/
通过配置settings.xml中的loaclRepository元素的值,可以设置本地仓库的目录。
中央仓库:
是一个默认的远程仓库,Maven的安装文件自带了中央仓库的配置。可以使用解压工具打开jar文件:Maven安装目录/lib/maven-model-builfer-3.x.x.jar(在Maven 2中, 对应 maven-2.2.1-uber.jar),然后访问路径org/apache/maven/model/pom-4.0.0.xml,可以看到该xml文件中配置了中央仓库的信息,如下:
<repositories> <repository><id>central</id><name>Central Repository</name><url>https://repo.maven.apache.org/maven2</url><layout>default</layout><snapshots><enabled>false</enabled></snapshots> </repository></repositories>
注:该pom-4.0.0.xml是所有Maven项目都会继承的超级POM
私服 :
架设在局域网内的仓库服务,用来代理广域网上的远程仓库,供局域网内的Maven用户使用。局域网仓库,具有节约外网带宽、加速Maven构建、提高稳定性、增强控制、降低中央仓库负荷等优点。
3、远程仓库的配置
如果默认的中央仓库没有需要的项目,可能项目需要的构件在另一个远程仓库,这时,就需要在项目POM中配置该仓库,如下:
在repositories元素下,可以使用repository子元素声明一个或者多个远程仓库。注意Maven自带的中央仓库使用的id为central,如果其他的仓库声明也使用该id,就会覆盖中央仓库的位置。
<project>...<repositories><repository><id>jboss</id><name>JBoss Repository</name><url>http://repository.jboss.com/maven2/</url><releases><enabled>true</enabled></releases><snapshots><enabled>false</enabled></snapshots><layout>default</layout></repository></repositories>...</project>
其中,releases元素控制Maven对于发布版构件的下载,例如releases元素的enabled值为ture,表示开启JBoss仓库的发布版本下载支持;
snapshots元素控制Maven对于快照版本构件的下载,例如snapshots元素的enabled值为false,表示关闭JBoss仓库的快照版本下载支持;
对于releases和snapshots来说,除了enabled,它们还包含另外两个子元素updatePolicy和checksumPolicy:
元素updatePolicy用来配置Maven从远程仓库检查更新的频率,默认的值是daily。其他值为:never、always、interval
元素checksumPolicy用来配置maven检查检验和文件的策略。默认值为warn,其他值为:fail 、ignore
(1)、远程仓库的认证
大部分远程仓库无须认证就可以访问,但有时出于安全考虑,需要提供认证信息才能访问一些远程仓库。为了能够访问需要认证信息的远程仓库,需要在settings.xml文件中配置认证信息。(为什么不能配置在POM中,而要配置在settings中?因为POM文件最终会被提交到代码仓库中,供所有人访问,settings一般只放在本机,更加安全)。
通过settings.xml中servers元素及其server子元素配置仓库认证信息,server子元素id标识需要认证的仓库,username、password标识用户名、密码。
(2)、部署至远程仓库
Maven可以将构件部署到远程仓库中,具体做法是:编辑项目pom.xml文件。配置distributionManagement元素,配置正确后执行 mvn clean deploy命令。
distributionmanagement包含repository和snapshotRepository子元素,前者表示发布版本构件的仓库,后者表示快照版本的仓库。
<?xml version="1.0" encoding="UTF-8"?><metadata><groupId>org.sonatype.nexus</groupId><artifactId>nexus</artifactId><versioning><latest>1.4.2-SNAPSHOT</latest><release>1.4.0</release><versions><version>1.3.5</version><version>1.3.6</version><version>1.4.0-SNAPSHOT</version><version>1.4.0</version><version>1.4.0.1-SNAPSHOT</version><version>1.4.1-SNAPSHOT</version><version>1.4.2-SNAPSHOT</version></versions><lastUpdated>20091214221557</lastUpdated></versioning></metadata>
<settings>...<mirrors><mirror><id>maven.net.cn</id><name>one of the central mirrors in China</name><url>http://maven.net.cn/content/groups/public/</url><mirrorOf>central</mirrorOf></mirror></mirrors>...</settings>
<settings>...<mirrors><mirror><id>interal-repository</id><name>Internal Repository Manager</name><url>http://192.168.1.100/maven2/</url><mirrorOf>*</mirrorOf></mirror></mirrors>...</settings>
- 掌握Maven_1
- 掌握
- 掌握 C#
- 系统掌握。
- 掌握 Ajax
- 掌握 Ajax
- 掌握 Ajax
- 掌握Ajax
- 掌握Ajax
- 掌握 Ajax
- 掌握 Ajax
- 掌握sizeof
- 掌握AJAX
- 掌握 Ajax
- 掌握sizeof
- 掌握AJAX
- 掌握udev
- 掌握 Ajax
- Myeclipse导入包出现不了Referenced Libraries
- Python中的MySQLConnector使用介绍
- ZCMU—1949
- 【IOS学习之常见问题】 App上架之发布App到Appstore 2(Application Loader的使用)
- LeetCode
- 掌握Maven_1
- Java基础拾遗:线程相关问题
- PX4源码分析6_uorb通信机制
- Hadoop--Hive安装错误解析
- JSP内置对象:在同一个页面实现成绩输入及总成绩显示
- 数据库中的事务是什么
- 第一天
- vim 插件 Ycm安装
- broadcom Knet 功能调试记录