Maven遵循【约定大于配置】规范,其强大之处其一就是有着丰富的插件生态系统。本文是对知识的一个汇总,多参考于网络资源。
versions-maven-plugin
一行命令同时修改maven项目中多个module的版本号。
一般略具规模的工程都是多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.-nameTHIRD-PARTY.txt|xargsgrepGPL|grep-vApache|grep-vMIT|grep-vCDDL ./dubbo-registry/dubbo-registry-nacos/target/generated-sources/license/THIRD-PARTY.txt:(GNU Lesser General Public License(LGPL), Version2.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), Version2.1)DataMapperforJackson(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可被赋值为localDevServer,localDevServer配置在~/.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来查看。
参考
一行命令同时修改maven项目中多个module的版本号
Maven插件wagon-maven-plugin自动化部署Java项目到Linux远程服务器
maven-replacer-plugin 静态资源版本号解决方案
用Maven部署war包到远程Tomcat服务器