maven 也遵循【约定大于配置】规范。maven 强大之处其一就是有着丰富的插件生态系统。本文是对知识的一个汇总,多参考于网络资源。
一句话功能:一行命令同时修改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命令一键修改版本号。
功能:检查三方库依赖的许可。
背景
最近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插件实现自动化构建部署到服务器
问题背景:本地的一个有前后端的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">
将项目的依赖文件,静态资源,配置信息,打包,打包格式如: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用于发布的插件,具备以下功能:
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>
最基本的功能:本地无需安装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 可用于执行 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是一个优秀的开源测试覆盖率统计工具。
pom.xml
运行命令生成报告:mvn cobertura:cobertura
一行命令同时修改maven项目中多个mudule的版本号
Maven插件wagon-maven-plugin自动化部署Java项目到Linux远程服务器
maven-replacer-plugin 静态资源版本号解决方案
用Maven部署war包到远程Tomcat服务器