高效使用maven插件

夏青青
2023-12-01

maven 也遵循【约定大于配置】规范。maven 强大之处其一就是有着丰富的插件生态系统。本文是对知识的一个汇总,多参考于网络资源。

versions-maven-plugin

一句话功能:一行命令同时修改maven项目中多个mudule的版本号。
一般略具规模的工程都是多module的项目,父模块包含多个子模块。
但是,这样的项目,在版本升级的时候就会比较麻烦,因为要遍历的修改所有pom中的版本号。比如要把0.0.1升级到0.0.2,那么就需要把所有的pom中的version都改掉。
在最外层的pom文件中,增加以下插件配置:

</plugins>
    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>versions-maven-plugin</artifactId>
        <version>2.7</version>
        <configuration>
            <generateBackupPoms>false</generateBackupPoms>
        </configuration>
    </plugin>
</plugins>

generateBackupPoms用于配置是否生成备份Pom,用于版本回滚。
配置好插件后,执行命令
mvn versions:set -DnewVersion=0.0.2
即可将以上例子中的所有版本号修改成0.0.2。
为了方便使用,还可以在linux上设置别名:
alias mvs='mvs() { mvn versions:set -DnewVersion=$1 }; mvs'
即可使用mvs命令一键修改版本号。

license-maven-plugin

功能:检查三方库依赖的许可。
背景
最近Dubbo的依赖的某三方库发现使用了LGPL的依赖,由于Dubbo在Apache基金会里面进行孵化,需要确保所有的三方依赖都和Apache许可证进行兼容。也就是说任何LGPL,GPL许可的三方依赖理论上都不能被纳入Dubbo的依赖,无论是直接依赖还是传递依赖。
解决方案
为了解决这个问题,maven的license插件提供许可证查询机制,命令(pom文件无需引入该GAV):
mvn license:add-third-party -Dlicense.useMissingFile
上述命令会自动扫描所有模块当中的依赖,包括直接和传递依赖,输出到每个模块的target/generated-sources/license/THIRD-PARTY.txt文件下,内容如下

Lists of 114 third-party dependencies.
     (ASF 2.0) Code Generation Library (cglib:cglib-nodep:2.2 - http://cglib.sourceforge.net/)

可以看到有一些依赖是暴露了双协议或者多协议,这种情况下可以选择兼容度最高的一种协议。例如logback作为一个典型的例子,就是暴露的是EPL+LGPL双协议,而EPL属于在Apache基金金下的Category B,即允许二进制形式的依赖,所以logback是允许作为三方依赖出现的。
为了排除这些双协议造成的干扰,采用如下命令进行过滤后,只剩下2条记录:

find . -name THIRD-PARTY.txt | xargs grep GPL | grep -v Apache | grep -v MIT | grep -v CDDL
./dubbo-registry/dubbo-registry-nacos/target/generated-sources/license/THIRD-PARTY.txt:
(GNU Lesser General Public License (LGPL), Version 2.1) Jackson(org.codehaus.jackson:jackson-core-lgpl:1.9.6 -http://jackson.codehaus.org)
./dubbo-registry/dubbo-registry-nacos/target/generated-sources/license/THIRD-PARTY.txt:
(GNU Lesser General Public License (LGPL), Version 2.1) DataMapper for Jackson (org.codehaus.jackson:jackson-mapper-lgpl:1.9.6-http://jackson.codehaus.org)

上述的依赖需要进行清理,nacos-client-1.0.0-RC3开始修复这个问题。
但是,三方依赖的optional依赖没法通过上述命令检测出来,例如nacos-client的如下依赖也是LGPL,用mvn license插件无法检查出来。

<dependency>
  <groupId>com.github.spotbugs</groupId>
  <artifactId>spotbugs-annotations</artifactId>
  <optional>true</optional>
</dependency>

事实上maven license插件提供一个选项,但是实际上对于三方依赖的optional依赖却不生效,原因待确定。个人推测如果在nacos-client下运行上述命令,应该是可以检查出来的。
总结
后续Dubbo每新增一个三方依赖,都需要检查License的兼容情况,尤其是三方依赖的optional依赖需要仔细检查,目前没有特别好的办法。

wagon-maven-plugin

参考wagon-maven-plugin插件实现自动化构建部署到服务器

maven-replacer-plugin

问题背景:本地的一个有前后端的demo有用(没有严格的前后端分离),静态资源放在webapp下面。更新静态资源文件之后,没有生效。
问题原因:浏览器缓存。
解决方案:使用 maven 的 com.google.code.maven-replacer-plugin 插件,在项目打包 package 时自动为静态文件追加 xxx.js?v=time 的后缀,从而解决浏览器修改后浏览器缓存问题,此插件只会在生成 war 包源码时生效,不需要修改任何代码。

原始文件和最终生成效果
原始文件:
<script src="${resource!}/js/xxx/xxx.js"></script>
打包后:
<script src="${resource!}/js/xxx/xxx.js?v=20180316082543"></script>

使用步骤
pom.xml 中插件添加

<properties>
    <!-- maven.build.timestamp 默认时间戳格式 -->
    <maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
</properties>
<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <configuration>
            <useCache>true</useCache>
        </configuration>
        <executions>
            <!-- 在打包之前执行,打包后包含已经执行后的文件 -->
            <execution>
                <id>prepare-war</id>
                <phase>prepare-package</phase>
                <goals>
                    <goal>exploded</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>com.google.code.maven-replacer-plugin</groupId>
        <artifactId>replacer</artifactId>
        <version>1.5.3</version>
        <executions>
            <!-- 打包前进行替换 -->
            <execution>
                <phase>prepare-package</phase>
                <goals>
                    <goal>replace</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <!-- 自动识别到项目target文件夹 -->
            <basedir>${build.directory}</basedir>
            <!-- 替换的文件所在目录规则 -->
            <includes>
                <include>${build.finalName}/WEB-INF/views/*.html</include>
                <include>${build.finalName}/WEB-INF/views/**/*.html</include>
            </includes>
            <replacements>
                <!-- 更改规则,在css/js文件末尾追加?v=时间戳,反斜杠表示字符转义 -->
                <replacement>
                    <token>\.css\"</token>
                    <value>.css?v=${maven.build.timestamp}\"</value>
                </replacement>
                <replacement>
                    <token>\.css\'</token>
                    <value>.css?v=${maven.build.timestamp}\'</value>
                </replacement>
                <replacement>
                    <token>\.js\"</token>
                    <value>.js?v=${maven.build.timestamp}\"</value>
                </replacement>
                <replacement>
                    <token>\.js\'</token>
                    <value>.js?v=${maven.build.timestamp}\'</value>
                </replacement>
            </replacements>
        </configuration>
    </plugin>
</plugins>

4.html中 css/js 文件引用规则
文件引用结尾处,必须是pom.xml文件中添加的规则:

<script src="${resource!}/js/xxx/xxx.js" type="text/javascript"></script>
<link href="${resource!}/css/xxx/xxx.css" rel="stylesheet" type="text/css">

maven-assembly-plugin

将项目的依赖文件,静态资源,配置信息,打包,打包格式如:zip、rar、tar.gz。
官网文档
pom.xml配置:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <descriptor>src/main/assembly/assembly.xml</descriptor>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

另外,需要配置一个assembly.xml文件。

maven release plugin

maven release plugin用于发布的插件,具备以下功能:

  • 把版本号SNAPSHOT去掉,向maven私服发布一个稳定版本
  • 检查项目中所有外部依赖包是否包含SNAPSHOT
  • 在git上面建立tag,作为release的milestone
  • 自动对当前版本号加1,为下一个迭代SNAPSHOT版本做好准备

pom.xml

<distributionManagement>
    <repository>
        <id>releases</id>
        <name>xxxx internal releases repository</name>
        <url>http://xxx.com/nexus/content/repositories/releases</url>
    </repository>
    <snapshotRepository>
        <id>snapshots</id>
        <name>xxxx internal snapshots repository</name>
        <url>http://xxx.com/nexus/content/repositories/snapshots</url>
    </snapshotRepository>
</distributionManagement>

<scm>
    <url>http://xxx.com/project</url>
    <connection>scm:git:git@xxx.com/project.git</connection>
    <developerConnection>scm:git:git@xxx.com/project.git</developerConnection>
    <tag>HEAD</tag>
</scm>

tomcat8-maven-plugin

最基本的功能:本地无需安装Tomcat容器,IDEA也无需配置Tomcat,使用tomcat8-maven-plugin即可启动一个内嵌式的Tomcat容器。这属于常规用法。下面稍微进阶一下。

犹记第一份工作,本地开发环境是Windows系统,应用却部署在Linux服务器里面。是故,本地测试时,需要打包应用生成war包,用SSH工具上传到Linux服务器指定目录,让Tomcat自动解包缩完成部署。
怎么将这一过程自动化呢?
借助于tomcat8-maven-plugin插件,利用Tomcat的manager模块来实现war包部署,须确保Tomcat安装Manager模块,一般默认安装,或者看webapp下有没有Manager目录。对本地的Tomcat的manager模块进行一些配置,打开本地Tomcat的tomcat-users.xml文件,增加配置:
<user username="johnny" password="awesome" roles="manager-script"/>
角色设定为manager-script,表明可使用Tomcat的manager模块的后台脚本管理,如果角色为manager-gui则表示此用户可使用manager模块的网页管理功能。对测试服务器也是类似的配置。

<properties>
    <warPackageName>demeApp</warPackageName>
    <tomcat.deploy.server>localDevServer</tomcat.deploy.server>
    <tomcat.deploy.serverUrl>http://localhost/manager/text</tomcat.deploy.serverUrl>
</properties>
<profiles>
    <profile>
        <id>deploy2test</id>
        <properties>
            <tomcat.deploy.server>testServer</tomcat.deploy.server>
            <tomcat.deploy.serverUrl>http://<host>:8080/manager/text</tomcat.deploy.serverUrl>
        </properties>
    </profile>
</profiles>
 
<build>
    <finalName>${warPackageName}</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat8-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <server>${tomcat.deploy.server}</server>
                <url>${tomcat.deploy.serverUrl}</url>
                <path>/${warPackageName}</path>
            </configuration>
        </plugin>
    </plugins>
</build>

configuration.server使用变量tomcat.deploy.server,实现将War包部署到不同服务器去,本地开发时tomcat.deploy.server可被赋值为localDevServerlocalDevServer配置在~/.m2/settings.xml中:

<servers>
	<!-- 可配置多个server表示不同的环境 -->
    <server>
        <id>localDevServer</id>
        <username>johnny</username>
        <password>awesome</password>
    </server>
</servers>

configuration.url默认值是http://localhost/manager/text,这个地址便是Tomcat的Manager模块的后台脚本入口。
configuration.path指定War包部署位置,如果path为/,也就是部署为ROOT.WAR。部署成功之后可以通过http://localhost/<path>来访问。

部署:mvn tomcat8:deploy,执行完命令后,应用就被打包部署到配置的Tomcat服务器上。通过-p参数来指定配置的多个profile其一:mvn tomcat8:deploy -Pdeploy2test
移除程序使用undeploy即可。

maven-surefire-plugin

插件 maven-surefire-plugin 可用于执行 JUnit 或 TestNG 的测试用例。在默认情况下,这个插件的test目标会自动执行测试源码路径下所有符合一组命名模式的测试类:
**/Test*.java:任何子目录下所有命名以Test开关的Java类。
**/*Test.java:任何子目录下所有命名以Test结尾的Java类。
**/*TestCase.java:任何子目录下所有命名以TestCase结尾的Java类。
pom.xml:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.20.1</version>
    <configuration>
        <suiteXmlFiles>
            <suiteXmlFile>./src/test/resources/testng.xml</suiteXmlFile>
        </suiteXmlFiles>
        <!--跳过测试运行,等价于mvn package -DskipTests-->
        <skip>true</skip>
        <!--跳过测试代码编译,等价于mvn package -Dmaven.test.skip=true-->
        <skipTests>true</skipTests>
        <!--mvn install Dtest,test参数用于在命令行中指定要运行的测试用例。如:
mvn test -Dtest=RandomGeneratorTest,使用通配符:mvn test -Dtest=Random*Test  
使用","号指定多个测试类:mvn test -Dtest=Random*Test,AccountCaptchaServiceTest-->
        <!--没有写UT也可以编译,不进行强校验,等同于mvn install Dtest -DfailIfNoTests=false-->
        <failIfNoTests>false</failIfNoTests>
        <!--用于额外的添加和排除-->
        <includes>
            <include></include>
        </includes>
        <includesFile></includesFile>
        <excludesFile></excludesFile>
        <excludedGroups></excludedGroups>
        <excludes>
            <exclude></exclude>
        </excludes>
    </configuration>
</plugin>

默认情况下,此插件在项目的target/surefire-reports目录下生成两种格式的错误报告。
简单文本格式——内容十分简单,可以看出哪个测试项出错。
与JUnit兼容的XML格式——XML格式已经成为Java单元测试报告的事实标准,这个文件可以用其他的工具如IDE来查看。

cobertura-maven-plugin

Cobertura是一个优秀的开源测试覆盖率统计工具。
pom.xml

运行命令生成报告:mvn cobertura:cobertura

参考

一行命令同时修改maven项目中多个mudule的版本号
Maven插件wagon-maven-plugin自动化部署Java项目到Linux远程服务器
maven-replacer-plugin 静态资源版本号解决方案
用Maven部署war包到远程Tomcat服务器

 类似资料: