maven生命周期和插件详解
生命周期和插件是Maven的两个核心概念,命令行的输入往往就对应了生命周期,如mvn package就表示执行默认生命周期阶段package。Maven的生命周期是抽象的,其实际行为都由插件来完成。Maven的生命周期是为了对所有的构建过程进行抽象和统一。
Maven拥有三套相互独立的生命周期,分别为clean、default和site。clean生命周期的目的是清理项目,default生命周期的目的是构建项目,site目的是建立项目站点。
clean:
1. pre-clean 执行一些清理前需要完成的工作。
2. clean 清理上一次构建生成的文件。
3. post-clean 执行一些清理后需要完成的工作。
default 包含的操作很多,以下列出主要的:
process-sources 处理项目主资源文件。一般来说,是对src/main/resources目录的内容进行变量替换等工作后,复制到项目输出的主classpath目录中。
compile 编译项目的主代码。一般来说,是编译src/main/java目录下的Java文件至项目输出的主classpath目录中。
process-test-sources 处理项目测试资源文件 src/main/resources。
test-compile 编译项目的测试代码。src/test/java。
test 使用单元测试框架运行测试,测试代码不会被打包或部署。
package 接受编译好的代码,打包成可发布的格式,如jar。
install 将包安装到Maven本地仓库,供本地其他Maven项目使用。
deploy 将最终的包复制到远程仓库。
site
pre-site
site 生成项目站点文档。
post-site
site-deploy 将生成的项目站点发布到服务器上。
插件目标(Plugin Goal):
一个插件往往能够完成多个任务。例如maven-dependency-plugin,它能够基于项目依赖做很多事情,例如分析项目依赖,帮助找出所有已解析的依赖等等,每个功能就是一个插件目标。用法是 <插件前缀:目标>。例如maven-dependency-plugin有十多个目标,最常用的:
mvn dependency:analyze //执行结果: [WARNING] Used undeclared dependencies found: [WARNING] org.springframework:spring-web:jar:5.0.4.RELEASE:compile [WARNING] org.springframework.boot:spring-boot-autoconfigure:jar:2.0.0.RELEASE:compile [WARNING] org.springframework:spring-tx:jar:5.0.4.RELEASE:compile [WARNING] org.springframework.boot:spring-boot:jar:2.0.0.RELEASE:compile [WARNING] Unused declared dependencies found: [WARNING] com.alibaba:fastjson:jar:1.2.31:compile [WARNING] org.springframework.boot:spring-boot-starter-test:jar:2.0.0.RELEASE:test [WARNING] org.springframework.boot:spring-boot-starter-web:jar:2.0.0.RELEASE:compile [WARNING] org.mybatis.spring.boot:mybatis-spring-boot-starter:jar:1.3.0:compile [WARNING] com.google.guava:guava:jar:23.0:compile
Unused declared dependencies found即声明了没使用的依赖,通过这个插件,就能看到项目依赖的情况。如果是因为继承了父pom文件而导致无用依赖太多,那么可以使用dependencyManagement管理。
插件绑定:
Maven的生命周期与插件相互绑定,用以完成实际的构建任务。例如项目编译这一任务,它对应了default生命周期的compile阶段,而maven-compile-plugin这一插件的compile目标能完成该任务。因此,将它们绑定,就能实现编译的目的。
Maven在核心为一些主要的生命周期阶段绑定了很多插件的目标,当用户通过命令行调用生命周期阶段的时候,对于的插件目标就会执行相应的任务。例如clean绑定mavevn-clean-plugin:clean。
而default生命周期,由于项目的打包类型会影响构建的具体过程,因此,default生命周期的阶段与插件的目标绑定关系由项目打包类型所决定,通过POM中的packaging元素定义。最常用的打包类型是jar。以下是基于jar,default生命周期的内置插件绑定关系:
default生命周期还有很多其他阶段,默认它们没有绑定任何插件,因此也没有实际行为。
自定义绑定:
除了内置绑定以外,用户还能够自己选择将某个插件目标绑定到生命周期的某个阶段上。例如一个常用的插件 Maven Archetype Plugin,用户通过这个插件可以生成一个Maven项目的骨架,也可以从一个现成的项目中生成模板。
通常的用法是使用 mvn archetype:create-from-project 指令生成模板。如果我正在编写一个模板项目,我希望在打包的时候自动生成模板,那么我可以把这个目标绑定到default的package生命周期上,如下配置:
</plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-archetype-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>create-archetype</id>
<phase>package</phase>
<goals>
<goal>create-from-project</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
在POM的build元素下的plugins子元素中声明插件的使用,除了配置插件的坐标声明外,还有插件的执行配置,executeions下每个execution子元素可以用来配置执行一个任务。我们配置了一个id为create-archetype的任务,通过phrase配置,将其绑定到package生命周期阶段上,再通过goals配置指定要执行的插件目标。
执行 mvn clean package 就能看到有以下输出:
//......以上省略...... [INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ demo --- [INFO] Building jar: /Users/yrw/Desktop/github/demo/target/demo-1.0-SNAPSHOT.jar [INFO] [INFO] >>> maven-archetype-plugin:3.0.1:create-from-project (create-archetype) > generate-sources @ demo >>> [INFO] [INFO] <<< maven-archetype-plugin:3.0.1:create-from-project (create-archetype) < generate-sources @ demo <<< [INFO] [INFO] [INFO] --- maven-archetype-plugin:3.0.1:create-from-project (create-archetype) @ demo --- [INFO] Setting default groupId: com.yrw [INFO] Setting default artifactId: demo [INFO] Setting default version: 1.0-SNAPSHOT [INFO] Setting default package: com.yrw.test [INFO] Scanning for projects... [INFO] [INFO] -----------------------< com.yrw:demo-archetype >----------------------- [INFO] Building demo-archetype 1.0-SNAPSHOT [INFO] --------------------------[ maven-archetype ]--------------------------- [INFO] [INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ demo-archetype --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 84 resources [INFO] [INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ demo-archetype --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 2 resources [INFO] [INFO] --- maven-archetype-plugin:3.0.1:jar (default-jar) @ demo-archetype --- [INFO] Building archetype jar: /Users/yrw/Desktop/github/demo/target/generated-sources/archetype/target/demo-archetype-1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.110 s [INFO] Finished at: 2018-11-23T22:12:15+08:00 [INFO] ------------------------------------------------------------------------ [INFO] Archetype project created in /Users/yrw/Desktop/github/demo/target/generated-sources/archetype [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 5.689 s [INFO] Finished at: 2018-11-23T22:12:15+08:00 [INFO] ------------------------------------------------------------------------
可以看到,在打包的时候执行了archetype:create-from-project,进入/target/generated-sources/archetype目录,就能看到生成的模板了。
命令行配置插件:
插件目标支持命令行配置,可以通过-D参数,并伴随一个参数=参数值的形式,来配置插件目标的参数。例如命令 mvn install -Dmaven.test.skip=true ,就会跳过执行测试。
在pom中配置全局插件:
并不是所有的插件参数都适合从命令行配置,有些参数的值从项目发布都不会改变,对于这种情况,可以在pom文件中一次性配置。例如需要配置maven-compiler-plugin编译java1.8.
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> <plugins> <build>
这样,不管绑定到compile阶段的maven-compiler-plugin:compile任务,还是绑定到test-compiler阶段的maven-compiler-plugin:testCompiler任务,就都能够使用该配置,基于1.8版本进行编译。