在项目里用了快一年的maven了,最近忽然发现maven项目在eclipse中build时很是慢,由于常常用clean install命令来build项目,也没有管那么多,但最近实在受不了乌龟同样的build速度,因而下定决心再看看《maven实战》吧,
对于我来讲,maven最主要的做用有两个方面,一个是对jar包的依赖解决功能,本身管理jar包,另外一个功能就是项目的构建,打包部署。如今我以为最重要的仍是maven的生命周期和插件机制,下面就来总结一下吧。css
Maven 官网:http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.htmlhtml
对于maven的生命周期来讲,共有三个相互独立的生命周期,分别是clean、default、site。clean生命周期目的是清理项目,default生命周期目的是构建项目,而site生命周期目的是创建项目站点。
每一个生命周期分别包含一些阶段,这些阶段是有顺序的,而且后面的阶段依赖于前面的阶段。如clean生命周期包含pre-clean、clean和post-clean三个阶段,若是执行clean阶段,则会先执行pre-clean阶段。
较之于生命周期阶段有先后依赖关系,三套生命周期自己是相互独立的,用户能够仅调用clean生命周期的某个阶段,也能够不执行clean周期,而直接执行default生命周期的某几个阶段。java
clean生命周期包含三个阶段,主要负责清理项目,以下:web
pre-clean | executes processes needed prior to the actual project cleaning |
clean | remove all files generated by the previous build |
post-clean | executes processes needed to finalize the project cleaning |
default生命周期定义了真正构建时所须要执行的全部步骤,包含的阶段以下:apache
validate | validate the project is correct and all necessary information is available. |
initialize | initialize build state, e.g. set properties or create directories. |
generate-sources | generate any source code for inclusion in compilation. |
process-sources | process the source code, for example to filter any values. |
generate-resources | generate resources for inclusion in the package. |
process-resources | copy and process the resources into the destination directory, ready for packaging. |
compile | compile the source code of the project. |
process-classes | post-process the generated files from compilation, for example to do bytecode enhancement on Java classes. |
generate-test-sources | generate any test source code for inclusion in compilation. |
process-test-sources | process the test source code, for example to filter any values. |
generate-test-resources | create resources for testing. |
process-test-resources | copy and process the resources into the test destination directory. |
test-compile | compile the test source code into the test destination directory |
process-test-classes | post-process the generated files from test compilation, for example to do bytecode enhancement on Java classes. For Maven 2.0.5 and above. |
test | run tests using a suitable unit testing framework. These tests should not require the code be packaged or deployed. |
prepare-package | perform any operations necessary to prepare a package before the actual packaging. This often results in an unpacked, processed version of the package. (Maven 2.1 and above) |
package | take the compiled code and package it in its distributable format, such as a JAR. |
pre-integration-test | perform actions required before integration tests are executed. This may involve things such as setting up the required environment. |
integration-test | process and deploy the package if necessary into an environment where integration tests can be run. |
post-integration-test | perform actions required after integration tests have been executed. This may including cleaning up the environment. |
verify | run any checks to verify the package is valid and meets quality criteria. |
install | install the package into the local repository, for use as a dependency in other projects locally. |
deploy | done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects. |
siet生命周期的目的是创建和发布项目站点,maven可以基于POM所包含的信息,自动生成一个友好的站点,方便团队交流和发布项目信息,包含的阶段以下:oracle
pre-site | executes processes needed prior to the actual project site generation |
site | generates the project's site documentation |
post-site | executes processes needed to finalize the site generation, and to prepare for site deployment |
site-deploy | deploys the generated site documentation to the specified web server |
从命令行执行maven任务的最主要方式就是调用maven的生命周期阶段。须要注意的是,各个生命周期是相互独立的,而一个生命周期的阶段是有先后依赖关系的。例子以下:
一、$mvn clean :该命令调用clean生命周期的clean阶段。实际执行的阶段为clean生命周期的pre-clean和clean阶段。
二、$mvn test:该命令调用default生命周期的test阶段。实际调用的是default生命周期的validate、initialize等,直到test的全部阶段。
三、$mvn clean install:该命令调换用clean生命周期的clean阶段和default生命周期的instal阶段。app
maven的核心仅仅定义了抽象的生命周期,具体的任务是交由插件完成的,插件以独立的形式存在。
对于插件自己,为了可以复用代码,它每每可以完成多个任务。如maven-dependency-plugin有十多个目标,每一个目标对应了一个功能,如 dependency:analyze、 dependency:tree和dependency:list。这是一种通用的写法,冒号前面是插件前缀,后面是该插件的目标。eclipse
maven的生命周期与插件相互绑定,用以完成实际的构建任务。具体而言,是生命周期的阶段与插件的目标相互绑定,已完成某个具体的构建任务。例如项目编译这一任务,它对应了default生命周期的compile阶段,而maven-compiler-plugin这一插件的compile目标可以完成该任务,所以将他们绑定。webapp
maven在核心为一些主要的生命周期接到绑定了不少插件的目标,以下:clean和site生命周期相对简单。maven
clean | clean:clean |
site | site:site |
site-deploy | site:deploy |
default生命周期与插件目标的绑定关系有点复杂一些。这是由于对于任何项目来讲,例如jar项目和war项目,他们的项目清理和站点生成任务是同样的,不过构建过程会有区别。例如jar项目须要打成jar包,而war项目须要打成war包。
因为项目的打包类型会影响构建的具体过程,所以,default生命周期的阶段与插件目标的绑定关系有项目打包类型所决定的,打包类型是经过pom中的packaging元素定义的。最多见的打包类型是jar,它也是默认的打包类型。基于该打包类型,default生命周期的内置绑定关系以下:
process-resources | resources:resources |
compile | compiler:compile |
process-test-resources | resources:testResources |
test-compile | compiler:testCompile |
test | surefire:test |
package | ejb:ejb or ejb3:ejb3 or jar:jar or par:par or rar:rar or war:war |
install | install:install |
deploy | deploy:deploy |
除了内置绑定觉得,用户还可以本身选择奖某个插件目标绑定到生命周期的某个阶段以执行更多更特点的任务。
<!-- 自动复制资源文件件到根目录 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.6</version> <configuration> <includeEmptyDirs>true</includeEmptyDirs> <encoding>GBK</encoding> <nonFilteredFileExtensions> <nonFilteredFileExtension>exe</nonFilteredFileExtension> <nonFilteredFileExtension>zip</nonFilteredFileExtension> <nonFilteredFileExtension>vbs</nonFilteredFileExtension> <nonFilteredFileExtension>sh</nonFilteredFileExtension> </nonFilteredFileExtensions> </configuration> <executions> <execution> <id>copy-resources</id> <phase>validate</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <includeEmptyDirs>true</includeEmptyDirs> <outputDirectory>${project.build.directory}</outputDirectory> <excludes> <exclude>agentmanager.jsmooth</exclude> <exclude>assembly.xml</exclude> </excludes> <resources> <resource> <directory>src/main/resources/</directory> <filtering>true</filtering> </resource> </resources> </configuration> </execution> </executions> </plugin>
如上图定义了一个id为copy-resources的任务,绑定到default生命周期的validate阶段,绑定的插件为maven-resources-plugin,插件目标为copy-resources。即用插件的copy-resources功能来实现项目资源文件的拷贝。
<!-- 自动复制maven依赖包到lib目录 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.1</version> <executions> <execution> <id>copy</id> <phase>install</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>lib</outputDirectory> </configuration> </execution> </executions> </plugin>
同上,定义了一个id为copy的任务,利用插件maven-dependency-plugin的copy-dependencies目标绑定到default生命周期的install阶段,来实现项目依赖的jar包的自动复制。
当插件目标被绑定到不一样的生命周期阶段时候,其执行顺序会有生命周期阶段的前后顺序决定的。若是多个目标被绑定到同一个阶段,他们的执行顺序是由插件声明的前后顺序决定目标的执行顺序。
用户能够配置插件目标的参数,进一步调整插件目标所执行的任务。
如 $mvn install -Dmaven.test.skip=true 的意义即跳过测试步骤。
参数-D的java自带的,其功能是经过命令行设置一个java系统属性,maven简单地重用了该参数以实现插件参数的配置。
如项目编译使用1.6版本的源文件,生成与JVM1.6兼容的字节码文件,以下:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin>
$mvn help:describe-Dplugin=org.apache.maven.plugins:maven-compiler-plugin:2.1 来获取插件的详细信息
能够简化为:
$mvn help:describe-Dplugin=compiler
若是仅仅描述插件目标的信息,能够加上goal参数:
$mvn help:describe-Dplugin=compiler-Dgoal=compile
若是想输出更详细的信息,能够加上detail参数:
$mvn help:describe-Dplugin=compiler-Ddetail
一个优秀的构建系统必须足够灵活,应该可以让项目在不一样的环境下都能成功构建。maven为了支持构建的灵活性,内置了三大特性,即:属性、profile和资源过滤。
maven属性分6类:
一、内置属性:如${basedir}表示项目根目录,${version}表示项目版本
二、POM属性:用户能够引用pom文件中对应的值。如:
${basedir} 项目根目录
${project.build.directory} 构建目录,缺省为target
${project.build.outputDirectory} 构建过程输出目录,缺省为target/classes
${project.build.finalName} 产出物名称,缺省为${project.artifactId}-${project.version}
${project.packaging} 打包类型,缺省为jar
${project.xxx} 当前pom文件的任意节点的内容
三、自定义属性:用户能够在pom的<properties>元素下自定义maven属性。
四、setting属性:用户可使用以settings开头的属性引用settings.xml中xml元素的值,如${settings.localRepository}指向用户本地仓库的地址。
五、java系统属性:maven可使用当前java系统的属性,如${user.home}指向了用户目录。
六、环境变量属性:全部环境变量均可以使用以env.开头的属性。如:${env.JAVA_HOE}。
这里所谓的资源:也就就是指src/main/resources和src/test/resources文件下的全部文件,默认状况下,这些文件会被复制到classpath下面,即target/classes下面。
所谓资源过滤,就是过滤这些文件夹下面的文件里面的内容,看里面的maven变量是否须要替换。默认状况下,只有pom.xml里面的变量才会被替换,资源文件是不会被过滤的,可是能够设置,以下:
<build> <finalName>agentmanager</finalName> <sourceDirectory>src/main/java</sourceDirectory> <resources> <!-- 控制资源文件的拷贝 --> <resource> <directory>src/main/resources</directory> <excludes> <exclude>**/jre.zip</exclude> <exclude>**/jre.tar</exclude> <exclude>agentmanager.jsmooth</exclude> <exclude>assembly.xml</exclude> </excludes> <targetPath>${project.build.directory}</targetPath> </resource> <resource> <directory>src/main/resources/conf</directory> <targetPath>${basedir}/conf</targetPath> <filtering>true</filtering> </resource> </resources> </build>
如jdbc.properties
jdbc.driverClassName=${db.driver} jdbc.url=${db.url} jdbc.username=${db.user} jdbc.password=${db.pwd}
profile文件
<profiles> <profile> <id>dev</id> <properties> <db.driver>oracle.jdbc.driver.OracleDriver</db.driver> <db.url>jdbc:oracle:thin:@10.252.48.3:1521:dbname</db.url> <db.user>username</db.user> <db.pwd>userpwd</db.pwd> </properties> </profile> <profile> <id>test</id> <properties> <db.driver>oracle.jdbc.driver.OracleDriver</db.driver> <db.url>jdbc:oracle:thin:@10.252.48.3:1521:testdbname</db.url> <db.user>testusername</db.user> <db.pwd>testuserpwd</db.pwd> </properties> </profile> </profiles>
在构建时可使用-P参数激活一个或多个profile,多个之间用逗号分隔
如 mvn clean install -Pdev
上面例子应该能够看出profile是作什么的,其实就至关于定义了一系列的profile变量,在具体构建时可用使用其中的某个profile去变量替换资源文件。
激活profile的方式有不少,如命令行激活(上面),settings文件显式激活、系统属性激活、操做系统环境激活、默认激活、文件存在与否激活等,具体能够参考官网资料。
根据须要,能够在如下文件声明profile。
一、pom.xml 针对当前项目
二、用户 settings.xml 用户目录下的.m2/settings.xml, 对当前用户的全部项目有效。
三、全局 settings.xml 即maven安装目录下的conf/settings.xml。对本机上的全部项目有效。
在maven的web项目里面,除了上面所说的资源文件(src/main/resources)以外,还有一类叫作web资源目录,即src/main/webapp下面的js、css等等。默认状况下,这些目录是不被资源过滤的,开启的命令以下:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.1.1</version> <configuration> <webResources> <resource> <directory>src/main/webapp</directory> <filtering>true</filtering> <includes> <include>**/*.css</include> <include>**/*.js</include> </includes> </resource> </webResources> </configuration> </plugin>