精通maven01

来源:互联网 发布:ctr数据 编辑:程序博客网 时间:2024/06/05 09:00

Maven的安装:

第一步:解压安装包,配置Path的环境变量;

第二步:修改conf文件夹下的配置文件settings.xml,在文件中加入下面这句话,目的是自定义Maven下载包的存放地址,也就是本地Maven仓库的地址;

<localRepository>D:/教学软件/Maven/MavenDownLoadLib/repository</localRepository>

第三步:Eclipse设置:Windows —>Preferences —>Maven —>Installation,点击add,地址不是bin也不是lib,是Maven的安装地址;Windows —>Preferences —>Maven —>User Settings,将settings.xml的路径写入User Settings,目的是为了让Maven使用这个设置文件;

Maven的常用命令:

mvn compile:编译,运行这个命令后Maven项目下会多一个target文件夹,这个文件夹中会有一个classes文件夹,里面装的就是我们项目java文件编译之后的class文件;

mvn test:编译并测试项目,最终在target文件夹中生成测试报告。注意,当我们右击某个项目的pom.xml文件并运行该命令是默认执行项目的src/test/java下名为Test***或***Test或***TestCase的类中的标注了@Test的方法

mvn clean:清空生成的文件,即删除target文件夹;

mvn package:生成target文件夹,编译、测试代码,生成测试报告,以及在target文件夹下生成项目的jar/war文件;

mvn install:将你打好的jar包安装到你的本地Maven库中,就是在我们设置的路径的。我们写的一个Maven项目A如果想要用另一个Maven项目B中的代码,除了要将B项目打包以及在A项目的pom.xml文件中写B项目的依赖外,还得使用这个命令来将B项目移到我们的本地仓库中;

mvn deploy:在整合或者发布环境下执行,将最终版本的包拷贝到远程的repository,使得其他的开发者或者工程可以共享。当用mvn install打出jar 包后,如果需要把该jar原封不动的deploy到mvn仓库中,可以执行如下命令:mvn deploy:deploy-file -Durl=url -DrepositoryId=repositoryId
-Dfile=file -DpomFile=pom.xml -Dversion=1.0;

-Durl:是指要deploy到仓库的路径;-DrepositoryId jar 包的repositoryid;-Dfile:jar包的具体路径; -DpomFile:jar对应的pom路径

-Dversion:jar的版本

如果是在DOS界面下,就必须在Maven项目的路径下输入上面的命令,系统才知道对哪个项目执行命令;如果在Eclipse中,则需要右击Maven项目中的pom.xml文件,然后选择run as–>Maven build…,在弹出的界面的Goals输入框中输入上面的maven命令就行了,注意不用输“mvn”。

在DOS界面下新建Maven项目的命令:mvn archetype:generate,然后选择archetype的版本,然后输入maven项目的项目名、模块名以及版本号;或者mvn archetype:generate -DgroupId=*** -DartifactId=*** -Dversion=***,选择archetype版本之后直接创建。

pom.xml文件相关标签的讲解:

<dependency>标签:当我们的maven项目需要导包时,就可以去Maven工厂的网址去拷贝导的包的<dependency>标签,然后复制到该项目的pom.xml文件的<dependencies>标签中,然后系统就会去本地maven工厂去找这个包,找不到就去总的Maven工厂去下载。

<dependency>标签下有三个基本标签:

<groupId>:总的项目名。我们以后都是将一个项目分成很多个模块来分工编写,每一个模块就是一个maven项目,而这个groupId就是总的项目名

<artifactId>:项目模块名,即maven项目名;

<version>:该maven项目的版本号;

这三个标签就像是maven仓库中的坐标,通过这三个标签系统才能找到目标包。当我们新建一个Maven项目,输入groupId和artifactId后,编辑器生成的Maven项目的src文件夹下的两个文件夹:/main/java和/test/java中都各有一个名为groupId.artifactId的包,我想这就是体现groupId和artifactId命名的地方。

<type>标签:<dependency>标签下的标签,表示依赖的类型。其默认是jar,当引入的<dependency>只是一个jar时就不用加了,如果是引入的是一个包含多个jar的项目时候,就要加上type标签值为pom。

<scope>标签:<dependency>标签下的标签,有5个值:

compile:scope的默认值,表示编译的时候依赖该dependency。Maven项目A中含有compile的dependency,Maven项目B依赖了项目A,那么B将自动依赖A中的compile的dependency,eclipse中我们点开B的Maven
Dependencies可以看到系统自动将A中compile的dependency的包导入到了B中,我们不需要再在B的pom.xml中写相关的dependency。当我们将项目A打包的时候也会将compile的dependency加进去,也就是会将该dependency指向的jar包放入A包中的lib里

runtime:表示在运行和测试系统的时候需要这个dependency,但在编译的时候不需要这个依赖。比如MySQL的连接驱动;

test:只在测试时使用,用于编译和运行测试代码。test的dependency不具有传递性,所以B依赖A,项目A的pom.xml文件中要写JUnit的dependency,项目B中同样还得写JUnit的dependency。Maven项目的架构中只有src/test/java文件夹下的包中的程序才能使用test的dependency,src/main/java文件夹下的包中的程序是用不了的,所以不要把测试相关的类写到main下。我们在对项目打包的时候,系统不会将test的dependency对应的jar包打到项目包中

provided:跟compile相似,但是表明了dependency 由JDK或者容器提供,例如Servlet API和一些Java EE APIs。这个scope 只能作用在编译和测试时,同时没有传递性。项目打包时不会将使用了provided的dependency打入项目包中,只是依赖过来。比如serverlet-api.jar,这个包在Tomcat等服务器上已经存在了,如果我们将项目打包的时候再将这个servlet-api.jar打入项目包中,就会和服务器上的包冲突;

system:类似provided,需要显式提供包含依赖的jar,Maven不会在Repository中查找它。

import:Maven 2.0.9 之后新增,它只使用在<dependencyManagement>中,表示从其它的pom中导入dependency的配置。

Maven的依赖特性:

我们知道通过继承一个项目我们可以在子项目中很好的申明需要使用的父项目的dependencyManagement定义的依赖项。但是因为每个项目都只能声明唯一的一个父项目,这在某些时候就会限制我们的项目建立。为此Maven为我们提供了一种方法,那就是通过设定依赖项的scope为import。比如我们有一个父项目A:

<groupId>groupA</groupId>

<artifactId>artifactA</artifactId>

<version>1.0</version>

<packaging>pom</packaging>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>test</groupId>

<artifactId>A</artifactId>

<version>1.0</version>

</dependency>

<dependency>

<groupId>test</groupId>

<artifactId>B</artifactId>

<version>1.1</version>

</dependency>

<dependency>

<groupId>test</groupId>

<artifactId>C</artifactId>

<version>1.2</version>

</dependency>

<dependency>

<groupId>test</groupId>

<artifactId>D</artifactId>

<version>1.3</version>

</dependency>

</dependencies>

</dependencyManagement>

我们的子项目B就可以像下面这样定义,左边是不用import的写法,而右边则是用了import的写法,右边就可以让子项目B依赖多个父类:

<parent>

<groupId>groupA</groupId>

<artifactId>artifactA</artifactId>

<version>1.0</version>

</parent>

<groupId>groupA</groupId>

<artifactId>artifactB</artifactId>

<version>1.0</version>

<packaging>pom</packaging>

<dependencies>

<dependency>

<groupId>test</groupId>

<artifactId>A</artifactId>

</dependency>

<dependency>

<groupId>test</groupId>

<artifactId>D</artifactId>

<scope>runtime</scope>

</dependency>

</dependencies>

<groupId>groupA</groupId>

<artifactId>artifactB</artifactId>

<version>1.0</version>

<packaging>pom</packaging>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>groupA</groupId>

<artifactId>artifactA</artifactId>

<version>1.0</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<dependencies>

<dependency>

<groupId>test</groupId>

<artifactId>A</artifactId>

</dependency>

<dependency>

<groupId>test</groupId>

<artifactId>D</artifactId>

<scope>runtime</scope>

</dependency>

</dependencies>

项目A依赖于temp-1.1.jar包,项目B依赖于temp-1.2.jar包,项目C依赖于项目A和项目B,那么C中会导入temp包的哪个版本呢?

答:项目C的pom.xml文件中先写哪个项目的依赖就导入哪个项目中的temp包。

项目A依赖于dbunit-2.2.jar,而dbunit-2.2.jar依赖于commons-logging-1.0.4.jar,项目B直接依赖于commons-logging-1.1.1.jar,项目C依赖于项目A和项目B,那么问C中会导入commons-logging的哪个版本?

答:哪个项目依赖commons-logging的级数少那就导入哪个项目的commons-logging,所以会导入项目B的commons-logging包。

我们可以在项目C的pom.xml中项目B的dependency标签中添加<exclusions>来达到不依赖项目B中的某些包的作用,如:

<exclusions>

<exclusion>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>//不用指定版本,因为项目B中只可能有一个版本的commons-logging包

</exclusion>

</exclusions>

这样,项目C中就不会导入项目B中的commons-logging包了。

聚合与继承

Maven的聚合

一个大项目我们可能会分很多模块,那就会有很多的Maven项目,编译起来就得一个一个编译,很麻烦。于是我们就有了聚合操作。如果使用Eclipse,那就只要新建一个Maven项目(新建的时候Packaging要选pom选项),该Maven项目中只要有一个pom.xml文件就好。然后我们在这个文件中添加如下代码:

如果不用Eclipse也行,我们可以在项目目录级别直接创建一个pom.xml文件,然后再在文件中写上面的代码,不过注意此时的路径要改一改,由于此时pom.xml文件与项目同级,所以上面的路径的返回上一级目录的”../”要去掉。

这样,user-core项目、user-log项目、user-service项目就聚合在一起,想要对这三个项目进行编译、打包等操作就只要直接右击新建的Maven项目的pom.xml文件选择相应的操作就好了。

视频中对承担模块聚合的pom.xml文件进行package操作,想要对三个模块进行打包,但是在为第三个项目打包时发生了编译错误。原因是user-service的测试类用到了user-core中的测试类的方法,但是打包的时候没有检测到user-service的测试类所用到的测试类,所以报错了。但是user-service的确是依赖了user-core,直接用user-core中的测试类并没有什么问题,测试也能测试,只是打包的时候出问题,这个问题有待以后查清。

解决方案呢,视频中是将用到的user-core中的测试类直接拷到user-service中,但是立马报错了,因为user-service已经依赖了user-core,能用到它里面的测试类,现在再复制过来就冲突了。所以建议还是新建一个Maven项目,将有关测试的程序全放到这里,这样就好了。

Maven的继承

我们发现我们写的user-core项目、user-log项目、user-service项目各自的pom.xml文件中都有重复的部分,比如:定义Maven中央仓库的网址的<url>http://maven.apache.org</url>,定义各种属性值的<properties>标签等等。为了解决重复,我们可以像上面一样创建一个Maven项目(Packaging为pom),名字可以叫user-parent。然后将三个项目的pom.xml文件中的重复部分直接拷贝到user-parent的pom.xml文件中,然后在各个文件中写<parent>标签来表明继承于user-parent项目,这样就OK了:

注意:继承的绝对路径是pom文件!

我们不仅可以将重复部分放到user-parent的pom.xml中,我们还可以将三个项目的pom.xml中的<dependency>标签全部复制到user-parent的pom.xml中的<dependencyManagement><dependencies></dependencies>

</dependencyManagement>中。此时user-parent的pom.xml就像一个工厂,其他继承的子项目在在pom.xml文件中写<dependency>标签想要导入某个包时就不用再指定<version>和<scope>两个标签了,只要指明groupId和artifactId就行了。

最后负责聚合的项目和负责继承的项目可以合二为一,形成最终的user-parent。

<dependencyManagement>与<dependencies>的区别:

<dependencyManagement>:一般存在于项目顶层模块的pom文件中(例如user-parent),通过它元素来管理jar包的版本,让子项目中引用一个依赖而不用显示的列出版本号。Maven 会沿着父子层次向上走,直到找到一个拥有dependencyManagement 元素的项目,然后它就会使用在这个dependencyManagement 元素中指定的版本号

所以dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。

<dependencies>:所有声明在dependencies里的依赖都会自动引入,并默认被所有的子项目继承。也就是说即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承)

私有仓库nexus

学Maven学到这里,我们知道了编写Maven项目的时候会用到两个仓库:本地仓库和中央仓库。我们在项目的pom.xml文件中写要导入包的<dependency>,然后系统就先去本地仓库中找,找不到就去中央仓库找。

但是有些公司都不提供外网给项目组人员,因此就不能使用maven访问中央仓库,所以很有必要在局域网里找一台有外网权限的机器,搭建nexus私服,然后开发人员连到这台私服上,这样的话就可以通过这台搭建了nexus私服的电脑访问maven的远程仓库。

如此一来开发人员要下载本地仓库没有的包的话就会去nexus私服上去找,如果私服上没有的话,那么就由私服向中央仓库发送下载请求。下载之后私服将包存在自己的工厂内,以供日后其他有需要的开发人员的下载。本地仓库、nexus私服、中央仓库这样的架构不仅能够使开发人员下载包下载得更快(因为是从局域网下载),而且能避免频繁访问中央仓库请求下载导致中央仓库认为是攻击性的访问而拒绝访问的情况。

nexus的安装:

第一步:下载安装包并解压。解压以后打开我们会发现有两个文件夹:nexus-2.3.1-01和sonatype-work,前一个文件夹就放了bin、lib、conf等nexus运行文件,后一个文件夹中有一个nexus的文件夹,这就是nexus私服存储从中央仓库下载的包;

第二步:老规矩,我们需要将nexus的bin目录放到path中去;

第三步:打开bin/jsw/conf/wrapper.conf文件,找到wrapper.java.command,这个变量是要你输入你电脑中jdk的java.exe文件的位置。所以我们令wrapper.java.command=D:\java\jdk1.8.0_77\bin\java;

第四步:DOS界面运行nexus install命令,安装完成之后运行nexus start命令打开nexus服务;

第五步:打开浏览器输入localhost:8081/nexus,进入nexus界面。点击log in登录,用户名密码分别是admin和admin123,接着我们就能进入私服管理界面;

第六步:配置远程索引。

新搭建的neuxs环境只是一个空的仓库,需要手动和远程中心库进行索引同步,nexus默认是关闭远程索引下载,最重要的一件事情就是开启远程索引下载。

我们需要找到仓库列表中的三个仓库ApacheSnapshots,Codehaus Snapshots和Central,在每个仓库的configuration下把Download Remote Indexes修改为true。然后分别右键三个仓库选择Update Index,Nexus会自动从远程中央仓库下载索引文件。

为了检验索引文件自动下载是否生效,可以却换到Browse Index ,如查看到有索引目录,表示已经OK 。或者使用左边菜单栏里的Artifact Search进行搜索, 在输入框里面输入你想要搜索的包名字,比如:maven, 如果有查询结果则表示同步索引成功(因为能够使用nexus搜索包的功能的前提是包在仓库中已经建立索引,没有建立索引或者索引不存在的情况下是搜索不到构建信息的):

还可以手动配置索引,方法就不在这里赘述,可访问如下两个网站:

http://www.myexception.cn/open-source/1961372.html

nexus中有很多仓库,这些仓库分为3中类型:

hosted:本地仓库,每个开发人员可以通过mvn deploy命令将jar包提交到的nexus私服的hosted类型的仓库,供别的开发人员下载。所以hosted类型的仓库都是对内部服务的,它不会面向公网,只是面向局域网。

hosted类型的仓库有三个:3rd party仓库存放我们编写项目的时候要用到的第三方包,有时候我们想要用的包在Maven中央工厂都找不到,只能从官网上下载,那么某个开发人员下载好后,就可以将这个包上传到3rd party仓库;Snapshots快照仓库用于保存开发过程中的不稳定版本,开发人员将自己编写的项目模块的打成jar包之后就可以上传到这个仓库;Releases发行仓库则是用来保存稳定的发行版本,开发人员将自己的项目模块的稳定版本的jar包上传到这个仓库。

proxy:代理仓库,它们被用来代理远程的公共仓库,如maven中央仓库。proxy类型的仓库就是私服存放从公网中下载的包的仓库。

proxy类型的仓库有三个:Central仓库就是存放nexus私服从Maven中央仓库下载的包;Apache Snapshots仓库用来存放Apache公司的Snapshots版本的包,Codehaus Snapshots则用来存放Codehaus公司的Snapshots版本的包。

group:仓库组,用来合并多个hosted/proxy仓库。

group类型的仓库有一个Public Repositories仓库,点击这个仓库就会出现如下界面对这个仓库进行设置。下图中的界面就表示Public Repositories仓库对Releases仓库、Snapshots仓库、3rd party仓库以及Central仓库进行了合并,我访问Public Repositories仓库的url就相当于访问这四个仓库

Maven项目连接私服仓库的配置——下载配置

那如何让我们编写的项目自动去nexus私服中去找依赖包呢?我们可以在user-parent项目的pom.xml文件中加入如下代码:

<repositories>

<repository>

<id>nexus</id>//设置仓库id

<name>Nesus Repository</name>//设置仓库名称,可以是中文

<url>http://localhost:8081/nexus/content/groups/public/</url>//指定仓库的url,这就告诉项目应该去哪里下载依赖包

//默认值为true,表示允许下载release版本的包

<release><enabled>true</enabled></release></repository>

//默认值为false,设置为true表示允许下载snapshot版本的包

<snapshot><>enabled>true</enabled></snapshot>

<repository>…</repository>//可以定义多个下载依赖包的仓库

</repositories>

上面的配置是针对项目而言的,我们每做一个项目就必须得在项目的parent模块的pom.xml文件中添加上面的配置。这虽然工作量不怎么大,但我们有更好的方法一次性解决所有项目去私服下载依赖包的问题。我们可以将上面的代码拷贝到Maven的settings.xml文件中的<profiles><profile></profile></profiles>标签中,然后加入以下代码激活这个<profile>

<activeProfiles>

<activeProfile>nexusProfile</activeProfile>//这里写要激活的repository所在的profile的id

</activeProfiles>

现在我们把各个项目parent模块中的<repositories>删掉,各个项目依然能通过settings.xml中的设置找到依赖包的仓库。

现在如果我们关掉nexus服务,系统先根据settings.xml文件<profile>中定义的仓库去找依赖包,这时发现settings.xml中的url指向的仓库连接不上,然后系统就会去Maven的中央仓库去找依赖包。为什么呢?我们可以打开maven包的lib文件夹,找到并打开maven-model-builder压缩包,org\apache\maven\model路径下有一个pom.xml文件,打开这个文件就会发现这个文件中定义了一个<id>为central、<url>为https://repo.maven.apache.org/maven2的<repository>,这就是连接中央工厂的设置,所以在连接不上settings.xml中设置的nexus私服仓库的情况下,系统会去中央仓库找依赖包。

那么如果我想要实现系统连不上私服仓库的情况下依然不会连接中央仓库,这该怎么配置呢?这就需要在settings.xml中配置镜像。

镜像的概念(http://my.oschina.net/sunchp/blog/100634):

mirror相当于一个拦截器,它会拦截maven对remote repository(远程仓库,私服和中央仓库都属于远程仓库)的相关请求,把请求里的remote repository地址,重定向到mirror里配置的地址。mirror的配置如下:

<mirrors>

<mirror>

<id>myMirror</id>

<mirrorOf>central</mirrorOf>

<name>Human Readable Name for this Mirror.</name>//mirror的name,自己随意定义

<url>http://localhost:8081/nexus/content/groups/public/</url>

</mirror>

</mirrors>

<mirrorOf>标签里面放置的是要被镜像的<repository>的id,<mirrorOf>*</mirrorOf>表示匹配所有远程仓库;<mirrorOf>repo1,repo2</mirrorOf>匹配仓库repo1和repo2,使用逗号分隔多个远程仓库;<mirrorOf>*,!repo1</miiroOf>匹配所有远程仓库,repo1除外,使用感叹号将仓库从匹配中排除。

上面的代码就设置了所有访问id为central的repository的请求都会被重定向到http://localhost:8081/nexus/content/groups/public/这个url中,这样一来系统只要尝试连接中央仓库,就会被重定向到私服的Public Repositories仓库。

不过还有一个问题,mirror只能完成对匹配远程仓库url的替换,而仓库的其他设置例如能不能下载release版本的包、能不能下载snapshots的包等等还是要依照<repository>中的设置。maven-model-builder中的id为central的repository已经定义不能下载snapshots版本的包,因此此时所有试图访问中央仓库的请求虽然被重定向到了私服中,但不能下载snapshots版本的包。如果想更改这个设置,我们可以将maven-model-builder中定义id为central的repository的那段代码复制到settings.xml中实现对maven-model-builder中repository的覆盖,然后激活这个repository的profile,接着修改snapshots的enabled为true就行了。

Maven项目连接私服仓库的配置——上传配置

上面讲解了实现Maven项目能够从私服仓库中下载依赖包的配置方法,接下来讲解实现将Maven项目上传到nexus私服的配置。

上面讲过项目发布的命令是mvn deploy,但光光输这个命令还是不够的。首先我们必须在user-parent项目的pom.xml文件中添加如下代码:

<distributionManagement>

<repository>

<id>user-release</id>

<name>user release resp</name>//name依然是随意定义

<url>http://localhost:8081/nexus/content/repositories/releases/</url>//表示发布到存放稳定版本的仓库

</repository>

<snapshotRepository>

<id>user-snapshot</id>

<name>user snapshot resp</name>

<url>http://localhost:8081/nexus/content/repositories/snapshots/</url>//表示发布到存放开发中版本的仓库

</snapshotRepository>

</distributionManagement>

上面的代码就设置了稳定版的项目和开发版的项目的发布仓库,当前版本的版本号也就是<version>标签如果包含SNAPSHOT则表示该项目是开发版本,提交的时候系统会自动将项目打包成jar包然后提交到<snapshotRepository>标签的url指定的仓库中去。如果当前的版本号如果包含RELEASE,则表示项目是稳定版,提交的时候会提交到<repository>标签的url指定的仓库中去。

接下来我们要为两种版本的发布配置权限,有权限才能发布到nexus私服上去。因此我们需要在settings.xml中配置如下代码:

<servers>

<server>

<id>user-release</id>//id要与上面一致

<username>deployment</username>//打开nexus的页面,点击Security下的Users,就可以看到UserID为deployment的用户是拥有发布权限的用户

<password>deployment123</password>

</server>

<server>

<id>user-snapshot</id>

<username>deployment</username>

<password>deployment123</password>

</server>

</servers>

这样就配置好了,我们右击user-parent的pom.xml文件选择maven build输入clean deploy命令就能实现项目的打包及发布。

Maven的生命周期和插件

生命周期与插件的关系:

Maven的核心是它的生命周期,生命周期什么都不做,因此Maven的安装文件很小。所有的事情都交给了插件来完成,在本地仓库的org\apache\maven\plugins目录下可以看到一些下载好的插件。比如说,Maven的default生命周期中定义了一个compile阶段,这个定义本身什么都不会做,真正编译代码的是groupId为org.apache.maven.plugins、artifactId为maven-compiler-plugin的Compiler插件。

在模板方法模式中,父类定义了一些抽象方法,并且决定这些方法的调用顺序,子类只需要实现这些方法。比如沏茶这个用例,父类定义的抽象方法有:烧开水,洗茶杯,倒水,放茶叶,并且有一个沏茶方法来顺序调用这些方法。而子类会去实现如何烧开水,如何洗茶杯,如何倒水,如何放茶叶。实例化一个子类之后,调用沏茶方法,这些步骤就会依次执行了。同样的道理,在Maven中,生命周期定义了编译,测试,打包,部署等等阶段,而插件会去实现这些对应的阶段,如上面提到的Compiler插件实现了如何编译。

三大生命周期:

Maven定义了三套生命周期:clean、default、site,每个生命周期都包含了一些阶段(phase)。

clean周期

pre-clean :执行清理前的准备工作;

clean :清理上一次构建生成的所有文件;

post-clean :执行清理后的工作

default周期是最核心的,它包含了构建项目时真正需要执行的所有步骤。

validate

initialize

generate-sources

process-sources :处理项目主资源文件。一般来说,是对src/main/resources目录的内容进行变量替换等工作后,复制到项目输出的主classpath目录中

generate-resources

process-resources :复制和处理资源文件到target目录,准备打包

compile :编译项目的源代码;一般来说,是编译src/main/java目录下的Java文件至项目输出的主classpath目录中

process-classes

generate-test-sources

process-test-sources :处理项目测试资源文件。一般来说,是对src/test/resources目录的内容进行变量替换等工作后,复制到项目输出的测试classpath目录中

generate-test-resources

process-test-resources

test-compile :编译测试源代码;一般来说,是编译src/test/java目录下的Java文件至项目输出的测试classpath目录中

process-test-classes

test : 使用单元测试框架运行测试代码,测试代码不会打包或部署

prepare-package

package :打包成jar或者war或者其他格式的可发布包

pre-integration-test

integration-test

post-integration-test

verify

install :将打好的包安装到Maven本地仓库,供本地其他Maven项目使用

deploy : 将最终的包复制到远程仓库,供其他开发人员和Maven项目使用

site周期

pre-site :执行一些在生成项目站点之前需要完成的工作

site :生成项目的站点文档;

post-site : 执行一些在生成项目站点之后需要完成的工作

site-deploy :发布生成的站点文档

三套生命周期相互独立,但各个生命周期中的phase却是有顺序的,且后面的phase依赖于前面的phase。执行某个phase时,其前面的phase会依顺序执行,但不会触发另外两套生命周期中的任何phase。从三个例子来进行说明:

1、mvn test : 该命令调用default生命周期的 test 阶段。实际执行的阶段为default生命周期的validate到test的所有阶段

2、mvn clean install : 该命令调用clean生命周期的clean阶段和default生命周期的install阶段。实际执行的是clean生命周期的pre-clean、clean阶段和default生命周期的validate到install的所有阶段。该命令结合了两个生命周期,是执行真正项目构建之前清理项目的一个很好的实践。

3、mvn clean deploy site-deploy : 该命令调用了clean生命周期的clean阶段和default生命周期的deploy阶段,以及site生命周期的site-deploy阶段。实际执行的是clean生命周期的pre-clean、clean阶段和default生命周期的所有阶段,以及site生命周期的所有阶段。

插件:

Maven的核心分发包只有不到3MB的大小,Maven会在需要的时候下载并使用插件。对于插件本身,为了能够复用代码,它往往能够完成多个任务。每一个任务就叫做插件的一个目标(我们可以把它想象成类的方法)。上面三个周期中的每个phase都是由相应的插件的某个目标来完成的,如执行mvn install命令时,调用的插件和执行的插件目标如下:

插件与生命周期的绑定:

内置绑定:Maven在核心为一些主要的生命周期阶段绑定了很多插件的目标。

clean生命周期phase与插件目标的绑定关系

生命周期阶段

clean

插件目标

maven-clean-plugin:clean

default生命周期与内置插件绑定关系及具体任务(打包类型: jar)

生命周期阶段

process-resources

compile

process-test-resources

test-compile

test

package

install

deploy

插件目标

maven-resources-plugin:resources

maven-compile-plugin:compile

maven-resources-plugin:testRresources

maven-compiler-plugin:testCompile

maven-surefire-plugin:test

maven-jar-plugin:jar

maven-install-plugin:install

maven-deploy-plugin:deploy

site生命周期阶段与插件目标的绑定关系

生命周期阶段

site

site-deploy

插件目标

maven-site-plugin:site

maven-site-plugin:deploy

用户自定义绑定:用户可以根据需要将任何插件目标绑定到任何生命周期的阶段,如:原来我们执行mvn package命令,系统会将编译后的class文件打到项目包中。

现在我们将maven-source-plugin插件的jar-no-fork目标绑定到default生命周期的package阶段。这样,以后在执行mvn package命令打包项目时,系统除了将class文件打一个包,还会在在package阶段之后会将项目的src/main下的源代码打一个包,生成如:ehcache-core-2.5.0-sources.jar形式的源码包。

例如我们在Maven项目user-core的pom.xml文件中添加如下代码:

<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-source-plugin</artifactId>

<version>2.2.1</version>

<executions>

<execution>

<id>attach-source</id>

<phase>package</phase><!– 要绑定到的生命周期的阶段 –>

<goals>

<goal>jar-no-fork</goal><!– 要绑定的插件的目标 –>

</goals>

</execution>

</executions>

</plugin>

</plugins>

</build>

这样右击user-core项目的pom.xml文件执行package命令,就会生成两个包,一个装class文件,一个装java文件。

视频中maven-source-plugin插件的其他两个目标:jar和test-jar,test-jar就是将src/test下的源码打包,而jar和jar-no-fork差不多,它俩的区别用到的时候可以上网查,这里就不赘述了。

Maven还有一个插件是用来配置编译的JDK版本的。在上面的<plugins>标签中添加如下代码,就能实现user-core项目在编译的时候按照JDK1.8的版本进行编译:

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.0</version>

<configuration>

<source>1.8</source>

<target>1.8</target>

</configuration>

</plugin>

Maven有一个插件可以将项目打成rar格式的包;

<plugin>

<groupId>org.apache.maven.plugin</groupId>

<artifactId>maven-rar-plugin</artifactId>

<version>2.3</version>

<executions><execution>

<goals><goal>rar</goal></goals>

<phase>package</phase>

</execution></executions>

<configuration>

<includeJar>true</includeJar>//includeJar标签默认是true表示打包的时候会将项目源码的jar包连同依赖jar包一起打成rar包,设置为false则表示最后生成的rar包不包括项目源码的jar包。

</configuration>

</plugin>

Maven中还能配置有关数据库的插件:

<plugin>

<groupId>org.codehaus.mojo</groupId>

<artifactId>sql-maven-plugin</artifactId>

<version>1.5</version>

<dependencies>//为这个插件引入mysql的jdbc包,这个依赖仅仅是在插件起作用的时候才被引入

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.24</version>

</dependency>

<dependencies>

<configuration>

<driver>com.mysql.jdbc.Driver</driver>

<username>root</username>

<password>123</password>

</configuration>

<executions>

<execution>

<id>create-db</id>

<phase>compile</phase>

<goals><goal>execute</goal></goals>

<configuration>

<sqlCommand>create database if not exists db_shop</sqlCommand>

</configuration>

</execution>

<execution>

<id>init-table</id>

<phase>test-compile</phase>

<goals><goal>execute</goal></goals>

<configuration>

<srcFiles>

<srcFile>src/main/resources/init.sql</srcFile>

</srcFiles>

</configuration>

</execution>

</executions>

</plugin>

某个项目只要引入了上面的插件,在compile这个项目的时候就会在mysql中创建一个名为db_shop数据库,在test-compile这个项目的时候就会将init.sql文件导入到mysql中。

这样每个Maven项目想要引用插件都得写上面的代码,这就产生重复了,因此我们可以将插件引用写在user-parent项目的pom.xml文件中:

<build>

<pluginManagment><plugins>

…..

</plugins></pluginManagment>

</build>

只要将设置插件的<plugin>标签复制到上面代码的省略号处,user-core、user-service等项目中只要在<plugin>中写明<groupId>和<artifactId>就行了。

在写项目时遇到的Maven问题:

1、Invalid classpath publish/export dependency /…

解决方案:项目右键>Properties -> Deployment Assembly -> Add,在弹出的框中选中Project,再选中无法依赖的项目,添加就好了。

2、Failure to transfer错误解决方法:

当我们去Maven中央仓库下载一个dependency,而网速过慢导致下载时间超过了maven设置的时间限制,就会报这个错误,解决方法就是去本地仓库中找到并删除这个下载到一半的dependency,然后右击项目–>maven–>update Project, 让eclipse重新下载就好了。



原文转载至:http://mojijs.com/2016/11/221010/index.html

0 0