目录
一、前言
事情是这样的:最近条线内部在搞“避免重复造轮子”的整改活动。其中发生了一个事情,之前条线内部的A团队已经尝鲜使用了XXL-job,后面考虑到避免重复造轮子,就要求B团队新建的系统也统一使用XXL-job,然后通过执行器进行权限管理,最后才发现原来A团队使用的那个版本还没有支持权限管理。从这里,我发现到一个问题:我们的maven管理确实很混乱,依赖版本管理必须得统一管理起来。
二、一团糟
实际上,日常工作中还有其他问题的:
“天啊,投产包为什么会是SNAPSHOT版本?”“哪位潇洒的大侠居然引用了一个快照版的三方包?坑爹啊”“我去,生产爆了个大bug,为什么你们系统没有?噢,原来我们用的版本不一样,你真幸运。”
以上的问题如何解决呢?其中一个答案就是:
统一我们的父pom【根】,然后要求所有团队的项目直接使用这个【根】或者再基于这个【根】进行继承成自己项目的二级父pom,通过这个二级父pom进行版本管理。
三、如何利用父pom
1、对于某些基础包进行统一版本管理。这样的话,当子pom引用的使用就只需要groupId和artifactId即可,且当父pom的版本一改,所有子pom就会统一自动继承。
<properties>
<java.version>1.8</java.version>
<maven.version>3.3.7</maven.version>
<mybatis.version>2.1.2</mybatis.version>
<enforcer.version>1.4.1</enforcer.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
</dependencies>
2、在父pom加入maven-enforcer-plugin进行规则校验。
之前在DevOps meetup上面京东数科DevOps落地实践的线上分享中提过他们的流水线上也会用到maven-enforcer-plugin。后面做了简单的试验并结合团队的实际情况,建议我们主要用以下几个校验规则。
-
requireMavenVersion - enforces the Maven version.
-
requireJavaVersion - enforces the JDK version.
-
requireReleaseVersion - enforces that the artifact is not a snapshot.
-
banDuplicatePomDependencyVersions - enforces that the project doesn't have duplicate declared dependencies.
-
requireReleaseDeps - enforces that no snapshots are included as dependencies.
-
bannedDependencies - enforces that excluded dependencies aren't included.
这里以我的其中一个项目父pom作为例子,里面存着以上头4个问题,然后我们跑一下mvn validate看会报什么错误。
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><packaging>pom</packaging><modules><module>validation</module><module>web</module></modules><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.13.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.imooc</groupId><artifactId>demoo</artifactId><version>0.0.1-SNAPSHOT</version><name>demoo</name><description>Demo project for Spring Boot</description><properties><java.version>1.10</java.version><maven.version>3.3.10</maven.version><mybatis.version>2.1.2</mybatis.version><enforcer.version>1.4.1</enforcer.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.version}</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.version}</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--引入JSR303校验--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.version}</version></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-enforcer-plugin</artifactId><version>${enforcer.version}</version><executions><execution><id>default-cli</id><goals><goal>display-info</goal><goal>enforce</goal></goals><phase>validate</phase><configuration><rules><!--Rule #1:检验maven版本--><requireMavenVersion><message><![CDATA[This application requires at least Maven with version ${maven.version}.]]></message><version>[${maven.version},)</version></requireMavenVersion><!--Rule #2:校验Java版本--><requireJavaVersion><message><![CDATA[This application requires at least JDK ${java.version}.]]></message><version>[${java.version}.0,)</version></requireJavaVersion><!--Rule #3:校验投产的版本不能是snapshot--><requireReleaseVersion><message>Snapshots version is prohibited.</message></requireReleaseVersion><!--Rule #4:校验pom文件中有没有重复的依赖(相同的GAV)--><banDuplicatePomDependencyVersions/><!--Rule #5:校验依赖冲突,如果冲突了会报错,然后在<excludes>进行排除管理即可--><bannedDependencies><!--校验传递性依赖(间接依赖)--><searchTransitive>true</searchTransitive><excludes/></bannedDependencies><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></executions></plugin></plugins></build></project>
当我们跑了mvn validate后,请大家对照以上pom文件看以下截图,你可以发现上面的头4个错误基本可以在构建环节直接识别,这样的话就可以在技术上有效的约束工作规范,这样是不是更好的体现“约定优于配置”呢?
当然,具体maven-enforcer-plugin还有更多的校验规则,或者你也可以基于它的规范开发你特有的校验规则。具体可以参考阿帕奇http://maven.apache.org/enforcer/maven-enforcer-plugin/index.html
四、后话
实际上这个就是我自己构想中的DevOps持续构建流水线上的关于质量关卡的其中一个小环节。诚然,在工程规约这个大命题下面,实际我们还有更多的事情需要做,后面再慢慢摸索,定期更新完善这个DevOps流水线。