1.Maven Enforcer plugin是什么鬼?
在说这个插件是什么前我们先思考这么一个问题:当我们开发人员进入项目组进行开发前,要准备开发环境,而领导总是会强调工具的统一,编译环境的统一。比如要求所有开发人员使用JDK1.8进行开发。
开发人员接下来就是去下载指定版本的JDK,然后开始开发。但是如果开发人员的机器配置比较多,有好几个版本的JDK,而他虽然下载了JDK1.8,但是忘记配置环境变量,很有可能他用了JDK1.6进行的编译。
问题有了,该如何解决? Maven Enforcer plugin就是来解决这类问题。Enforcer可以在项目validate时,对项目环境进行检查。
2.Maven Enforcer plugin怎么用?
Enforcer配置后默认会在validate后执行enforcer:enforce,然后对项目环境进行检查。拿上面对JDK的校验为例,我们在pom.xml中配置插件。
<?xml version="1.0" encoding="UTF-8"?> <project> ... <build> <plugins> <plugin> <artifactId>maven-enforcer-plugin</artifactId> <version>1.4.1</version> <executions> <execution> <id>default-cli</id> <goals> <goal>enforce</goal> </goals> <phase>validate</phase> <configuration> <rules> <requireJavaVersion> <message> <![CDATA[You are running an older version of Java. This application requires at least JDK ${java.version}.]]> </message> <version>[${java.version}.0,)</version> </requireJavaVersion> </rules> </configuration> </execution> </executions> </plugin> </plugins> </build> <properties> <java.version>1.8</java.version> </properties> </project>
我本地配置没有JDK1.8,按照我的期望,执行maven命令时应该会失败。让我们来执行命令 mvn validate 会打出如下日志告知我们JDK版本过低。
qyfmac$ mvn validate [INFO] Scanning for projects... [INFO] ------------------------------------------------------------------------ [INFO] Reactor Build Order: [INFO] [INFO] AppFuse Modular Application [INFO] AppFuse Modular Application - Core [INFO] AppFuse Modular Application - Web (Spring MVC) [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building AppFuse Modular Application 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-enforcer-plugin:1.4.1:enforce (enforce-versions) @ stock --- [WARNING] Rule 1: org.apache.maven.plugins.enforcer.RequireJavaVersion failed with message: You are running an older version of Java. This application requires at least JDK 1.8. [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] [INFO] AppFuse Modular Application ........................ FAILURE [ 0.987 s] [INFO] AppFuse Modular Application - Core ................. SKIPPED [INFO] AppFuse Modular Application - Web (Spring MVC) ..... SKIPPED [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.886 s [INFO] Finished at: 2015-09-22T15:37:04+08:00 [INFO] Final Memory: 16M/156M [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal org.apache.maven.plugins:maven-enforcer-plugin:1.4.1:enforce (enforce-versions) on project stock: Some Enforcer rules have failed. Look above for specific messages explaining why the rule failed. -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
其实执行命令 mvn enforcer:enforce 也可以达到上面的效果。区别就是validate是maven全局命令,enforcer:enforce是只执行这个插件的命令。
这里要注意一点,执行enforcer:enforce时,id必须是default-cli(具体原因请参阅:http://stackoverflow.com/questions/24827194/maven-enforcer-plugin-missing-or-invalid-rules),否则会报
The parameters 'rules' for goal org.apache.maven.plugins:maven-enforcer-plugin:1.4.1:enforce are missing or invalid
3.Maven Enforcer plugin标签详解
现在对这个插件的配置讲解一下。
<plugin> <artifactId>maven-enforcer-plugin</artifactId> <version>1.4.1</version> <executions> <execution> <id>default-cli</id> --一个执行实例的id <goals> <goal>enforce</goal> --执行的命令 </goals> <phase>validate</phase> --执行的阶段 <configuration> <rules> --规则 <requireJavaVersion> --JDK的版本 <message> --失败后提示消息 <![CDATA[You are running an older version of Java. This application requires at least JDK ${java.version}.]]> </message> <version>[${java.version}.0,)</version> --JDK版本规则 </requireJavaVersion> </rules> </configuration> </execution> </executions> </plugin>
Enforcer的rules除了控制JDK版本,还有很多其他规则,甚至可以通过它的接口自定义。
- alwaysFail – Always fail… used to test plugin configuration.
- alwaysPass – Always passes… used to test plugin configuration.
- banDistributionManagement – enforces that project doesn’t have distributionManagement.
- bannedDependencies – enforces that excluded dependencies aren’t included.
- bannedPlugins – enforces that specific plugins aren’t included in the build.
- bannedRepositories – enforces to not include banned repositories.
- banTransitiveDependencies – enforces that project doesn’t have transitive dependencies.
- dependencyConvergence – ensure all dependencies converge to the same version.
- evaluateBeanshell – evaluates a beanshell script.
- reactorModuleConvergence – enforces that a multi module build follows best practice.
- requireActiveProfile – enforces one or more active profiles.
- requireEnvironmentVariable – enforces the existence of an environment variable
- requireFilesDontExist – enforces that the list of files does not exist.
- requireFilesExist – enforces that the list of files does exist.
- requireFilesSize – enforces that the list of files exists and is within a certain size range.
- requireJavaVersion – enforces the JDK version.
- requireMavenVersion – enforces the Maven version.
- requireNoRepositories – enforces to not include repositories.
- requireOS – enforces the OS / CPU Architecture.
- requirePluginVersions – enforces that all plugins have a specified version.
- requirePrerequisite – enforces that prerequisites have been specified.
- requireProperty – enforces the existence and values of properties.
- requireReleaseDeps – enforces that no snapshots are included as dependencies.
- requireReleaseVersion – enforces that the artifact is not a snapshot.
- requireSameVersions – enforces that specific dependencies and/or plugins have the same version.
- requireUpperBoundDeps – ensures that every (transitive) dependency is resolved to it’s specified version or higher.
You may also create and inject your own custom rules by following the maven-enforcer-rule-api instructions.
我们再写一个例子。比如除了需要限制JDK外,我们还要限定maven版本,项目不得包含TestNG依赖,操作系统必须是mac os x 64位,项目版本号在执行install时必须是正式版本
直接上代码:
<?xml version="1.0" encoding="UTF-8"?> <project> ... <build> <plugins> <plugin> <artifactId>maven-enforcer-plugin</artifactId> <version>1.4.1</version> <executions> <execution> <id>default-cli</id> <goals> <goal>display-info</goal> <goal>enforce</goal> </goals> <phase>validate</phase> <configuration> <rules> <requireMavenVersion> <message> <![CDATA[You are running an older version of Maven. This application requires at least Maven ${maven.version}.]]> </message> <version>[${maven.version},)</version> </requireMavenVersion> <requireJavaVersion> <message> <![CDATA[You are running an older version of Java. This application requires at least JDK ${java.version}.]]> </message> <version>[${java.version}.0,)</version> </requireJavaVersion> <bannedDependencies> <!--是否检查传递性依赖(间接依赖)--> <searchTransitive>true</searchTransitive> <excludes> <!--groupId[:artifactId][:version][:type][:scope][:classifier]-->
<exclude>org.testng:testng</exclude> </excludes> <message>don't use TestNG,must use JUnit</message> </bannedDependencies> <requireOS> <name>mac os x</name> <family>mac</family> <arch>x86_64</arch> <version>10.10.3</version> </requireOS> <requireProperty> <property>project.version</property> <message>"Project version must be specified."</message> <regex>.*(\d|-SNAPSHOT)$</regex> <regexMessage>"Project version must end in a number or -SNAPSHOT."</regexMessage> </requireProperty> </rules> </configuration> </execution> <execution> <id>enforce-install</id> <goals> <goal>enforce</goal> </goals> <phase>install</phase> <configuration> <rules> <requireProperty> <property>project.version</property> <message>"Project version must be specified."</message> <regex>.*(\d)$</regex> <regexMessage>"Project version must end in a number."</regexMessage> </requireProperty> </rules> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> ... <!--测试放开--> <!--<dependency>--> <!--<groupId>org.testng</groupId>--> <!--<artifactId>testng</artifactId>--> <!--<version>6.1.1</version>--> <!--<scope>test</scope>--> <!--</dependency>--> </dependencies> <properties> <java.version>1.7</java.version> <maven.version>3.3.3</maven.version> </properties> </project>
这里要说一下requireOS了,不支持表达式,必须准确的写一个版本号,个人认为这个不好,不过可以把version注释掉,不校验操作系统的版本。
如果某些情况下不检查环境,可以在maven命令上加一个 -Denforcer.skip=true 来跳过enforcer插件执行。
例如:mvn clean validate -Denforcer.skip=true
更多神奇的配置方式还请参阅官方网站 :http://maven.apache.org/enforcer/maven-enforcer-plugin/index.html。
我们会经常碰到这样的问题,在pom中引入了一个jar,里面默认依赖了其他的jar包。jar包一多的时候,我们很难确认哪些jar是我们需要的,哪些jar是冲突的。此时会出现很多莫名其妙的问题,什么类找不到啦,方法找不到啦,这种可能的原因就是jar的版本不是我们所设想的版本,但是我们也不知道低版本的jar是从哪个maven里面引用的。此时我们的maven-enforcer-plugin就可以登场了。
<project>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce</id>
<configuration>
<rules>
<dependencyConvergence/>
</rules>
</configuration>
<goals>
<goal>enforce</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
...
</project>
在进行mvn clean package的时候,会在console中打印出来冲突的jar版本和其父pom,如下:
Dependency convergence error for org.slf4j:slf4j-api1.6.1 paths to dependency are:
[ERROR]
Dependency convergence error for org.slf4j:slf4j-api:1.6.1 paths to dependency are:
+-org.myorg:my-project:1.0.0-SNAPSHOT
+-org.slf4j:slf4j-jdk14:1.6.1
+-org.slf4j:slf4j-api:1.6.1
and
+-org.myorg:my-project:1.0.0-SNAPSHOT
+-org.slf4j:slf4j-nop:1.6.0
+-org.slf4j:slf4j-api:1.6.0
这个时候,我们看一眼就知道应该把那个dependency中的哪个jar进行exclude。
这是一个小技巧,不过很管用。
转载请注明:学时网 » 学习Maven之Maven Enforcer Plugin