1. 背景
當(dāng)我們使用maven管理jar包依賴時(shí)悬槽,經(jīng)常會(huì)發(fā)生jar包沖突的情況,大多數(shù)時(shí)候影斑,可能就是排除一下沖突包就可以给赞,但可能呢,你發(fā)現(xiàn)就只修改了一個(gè)jar包的依賴矫户,項(xiàng)目啟動(dòng)時(shí)片迅,就會(huì)報(bào)各種各樣的異常,比如某個(gè)類皆辽,或是方法找不到障涯。
造成上面的情況罐旗,主要原因是修改某一個(gè)依賴后,最終有效的jar包列表發(fā)生了變化唯蝶,我們需要能有一個(gè)好的辦法九秀,可以快速知道修改前后的jar包變化呢,這樣對(duì)于我們排除就會(huì)比較方便一點(diǎn)粘我,下面的處理可能會(huì)對(duì)你有幫助鼓蜒。
2. 處理后的對(duì)比輸出
我們先來看一下,我們經(jīng)過處理后征字,得到的對(duì)比結(jié)果
從上面的輸出(用printf格式化輸出都弹,看得方便一點(diǎn))我們可以清晰看出:
- 一共有多少個(gè)差異,比如上面共有9個(gè)差異
- 列表中可以看出groupId匙姜,artifactId
- 最后是版本號(hào)對(duì)比畅厢,可能其中一個(gè)版本缺少了某個(gè)jar,可以清晰地看出來
3. 實(shí)現(xiàn)步驟
-
第一步 生成第1個(gè)依賴樹文件
在命令行氮昧,進(jìn)入項(xiàng)目的目錄框杜,用命令生成依賴樹文件
mvn dependency:tree > project_dependency_1.0.1.txt
這樣我們就會(huì)在項(xiàng)目目錄下,生成1.0.1版本的依賴樹文件
-
第二步 生成第2個(gè)依賴樹文件
回到項(xiàng)目中袖肥,修改相應(yīng)的依賴版本咪辱,再回到目錄,生成第2個(gè)依賴樹文件
mvn dependency:tree > project_dependency_1.0.2.txt
這時(shí)椎组,就會(huì)在我們的項(xiàng)目目錄下油狂,生成兩個(gè)依賴樹文件
project_dependency_1.0.1.txt
project_dependency_1.0.2.txt
-
第三步 解析這兩個(gè)文件,輸出對(duì)比
我們先看依賴樹文件寸癌,我們關(guān)注的是下面一段
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ project_name ---
[INFO] +- com.github.knightliao.apollo:apollo:jar:1.0.14:compile
[INFO] | +- commons-lang:commons-lang:jar:2.4:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-core:jar:2.6.0:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-databind:jar:2.6.0:compile
[INFO] | | \- com.fasterxml.jackson.core:jackson-annotations:jar:2.6.0:compile
[INFO] | +- com.google.code.gson:gson:jar:2.3:compile
[INFO] | +- javax.servlet:servlet-api:jar:2.4:compile
[INFO] | \- redis.clients:jedis:jar:2.1.0:compile
我們主要關(guān)注這3個(gè)點(diǎn):
- 真實(shí)解析出來的依賴樹的開始輸出位置专筷,就是下面這個(gè)標(biāo)識(shí)開始
maven-dependency-plugin - 提取特征呢,我們以某一行是包含jar字符串
- 解析出groupId,artifactId,version
比如從這一行蒸苇,我們可以解析出來
[INFO] | \- redis.clients:jedis:jar:2.1.0:compile
groupId : 第一個(gè)冒號(hào)前
artifactId : 第一個(gè)冒號(hào)與第2個(gè)冒號(hào)之間
version: 第2個(gè)冒號(hào)到":compile"串前
下面是實(shí)現(xiàn)代碼
public class MavenDepenTreeCompare {
public static void main(String[] args) throws IOException {
//依賴樹文件
String parentPath = "這里請(qǐng)?zhí)鎿Q成你輸出文件的目錄";
String name1 = "project_dependency_1.0.1.txt";
String name2 = "project_dependency_1.0.2.txt";
//從兩個(gè)文件中磷蛹,讀取出依賴版本信息
List<JarInfo> v1List = getJarInfoList(parentPath+name1);
List<JarInfo> v2List = getJarInfoList(parentPath+name2);
Set<JarInfo> vAllSet = new LinkedHashSet<JarInfo>();
vAllSet.addAll(v1List);
vAllSet.addAll(v2List);
//版本比較并輸出
compareVersion(v1List,v2List,vAllSet);
}
//從文件獲得jarInfo列表
public static List<JarInfo> getJarInfoList(String filePath) throws IOException{
List<JarInfo> resultList = new ArrayList<JarInfo>();
List<String> fileList = FileUtils.readLines(new File(filePath));
boolean rowBegin = false;
String beginFlag = "maven-dependency-plugin";
for(String row : fileList) {
if(!rowBegin && row.indexOf(beginFlag)>=0) {
rowBegin = true;
}
if(!rowBegin) {
continue;
}
JarInfo jarInfo = getJarVersion(row);
if(null==jarInfo) {
continue;
}
resultList.add(jarInfo);
}
return resultList;
}
//從list查找,找到則返回填渠,找不到則返回null
public static JarInfo findJar(JarInfo info,List<JarInfo> infoList) {
JarInfo result = null;
int findIndex = infoList.indexOf(info);
if(findIndex<0) {
return result;
}else {
return infoList.get(findIndex);
}
}
//比較兩個(gè)列表,并進(jìn)行格式化輸出
public static void compareVersion(List<JarInfo> v1List,List<JarInfo> v2List,Set<JarInfo> vAllSet) {
int index = 0;
for(JarInfo jarInfo : vAllSet) {
JarInfo v1Info = findJar(jarInfo,v1List);
JarInfo v2Info = findJar(jarInfo,v2List);
if(v1Info==null || v2Info==null) {
System.out.printf("%-3s %-50s【%s ~ %s】\r\n",
++index , jarInfo.getArtifactInfo(),v1Info==null?"":v1Info.version,v2Info==null?"":v2Info.version);
continue;
}
if(!v1Info.version.equals(v2Info.version)) {
System.out.printf("%-3s %-50s【%s ~ %s】\r\n",
++index , jarInfo.getArtifactInfo(),v1Info.version,v2Info.version);
}
}
}
//根據(jù)字符串行鸟辅,生成依賴信息
public static JarInfo getJarVersion(String row) {
if(row.indexOf("jar")>=0) {
row = row.replace(":jar", "");
String jarInfoStr = row.substring(row.lastIndexOf(" ")+1, row.indexOf(":compile"));
int firstIndex = jarInfoStr.indexOf(":");
int secondIndex = jarInfoStr.lastIndexOf(":");
return new JarInfo(jarInfoStr.substring(0,firstIndex),jarInfoStr.substring(firstIndex+1,secondIndex),jarInfoStr.substring(secondIndex+1));
}else {
return null;
}
}
//用來存放groupId,artifactId,version信息
static class JarInfo {
public String groupId;
public String artifactId;
private String version;
public JarInfo(String groupId,String artifactId,String version) {
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((artifactId == null) ? 0 : artifactId.hashCode());
result = prime * result + ((groupId == null) ? 0 : groupId.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
JarInfo other = (JarInfo) obj;
if (artifactId == null) {
if (other.artifactId != null)
return false;
} else if (!artifactId.equals(other.artifactId))
return false;
if (groupId == null) {
if (other.groupId != null)
return false;
} else if (!groupId.equals(other.groupId))
return false;
return true;
}
@Override
public String toString() {
return groupId + "." + artifactId + "." + version;
}
public String getArtifactInfo() {
return groupId + "." + artifactId;
}
}
}
最終的輸出結(jié)果呢氛什,就是上面貼出來的。
是否對(duì)您有幫助呢匪凉,可以點(diǎn)個(gè)贊哦枪眉!