【Maven】持续交付环境中,组件工程依赖管理的配置与检查

一、背景

  • 组件类工程A,打包后生成jar包t,该jar包可以作为组件供其他工程使用;
  • 组件类工程A依赖jar包a,jar包a默认依赖版本n的jar包b;
  • 工程B依赖jar包t。
本文使用jar包slf4j-log4j12-1.7.21.jar为jar包a的样例,slf4j-api-1.7.21.jar为jar包b的样例,版本n为1.7.21。

二、详细配置

  • 工程A的pom配置

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.titan</groupId>
	<artifactId>testa</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>testa</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.21</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

  • 工程A的依赖情况

  • 工程B的pom配置
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.titan</groupId>
	<artifactId>testb</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>testb</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.titan</groupId>
			<artifactId>testa</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>
  • 工程B的pom依赖情况

  • 结论
由此可以得出,工程A依赖jar包org.slf4j:slf4j-log4j12:jar:1.7.21,进而依赖jar包org.slf4j:slf4j-api:jar:1.7.21。
工程B依赖jar包com.titan:testa:jar:0.0.1-snapshot,继承该jar包的依赖关系,依赖jar包org.slf4j:slf4j-log4j12:jar:1.7.21,进而依赖jar包org.slf4j:slf4j-api:jar:1.7.21。

三、遇到问题
  • 工程A的开发团队突然发现版本n的jar包b(即样例中的org.slf4j:slf4j-api:jar:1.7.21)存在安全或者性能问题,需要替换为版本m的新jar包(org.slf4j:slf4j-api:jar:1.7.25);
  • 在工程A升级之后,重新打包B时,除修改引入依赖A的版本之外,不需要再修改其他配置,就能够保证工程B顺利使用正确的jar包依赖。
采取的方案为在工程A的pom中配置dependency management,设置 org.slf4j:slf4j-api:jar的版本为1.7.25。

四、解决方案

  • 工程A的pom配置
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.titan</groupId>
	<artifactId>testa</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>testa</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.21</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.slf4j</groupId>
				<artifactId>slf4j-api</artifactId>
				<version>1.7.25</version>
			</dependency>
		</dependencies>
	</dependencyManagement>
</project>
  • 工程A的依赖情况

由此可以看到,org.slf4j:slf4j-api:jar的版本已经被设置为1.7.25。
  • 工程B的pom依赖情况(修改工程A的pom后,注意install工程A)

发现工程B并未受到工程A中配置的dependency management的影响。
只有对工程A进行优化配置,在dependency中明确指定org.slf4j:slf4j-api的jar包版本,这样就能够传递到工程B中。
  • 优化后工程A的pom配置
在工程A的pom文件中明文指定org.slf4j:slf4j-api:jar的版本。
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.titan</groupId>
	<artifactId>testa</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>testa</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.21</version>
		</dependency>
		
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.slf4j</groupId>
				<artifactId>slf4j-api</artifactId>
				<version>1.7.25</version>
			</dependency>
		</dependencies>
	</dependencyManagement>
</project>

  • 优化后工程A的依赖情况

提示org.slf4j:slf4j-api:jar该jar包版本冲突,同时如我们所愿被强制设置使用1.7.25。
  • 优化后工程B的pom依赖情况

根据上述内容,可以发现工程B的依赖发生了冲突,并且该冲突没有明确指明使用哪个版本的jar包,这种情况在持续集成过程中是不允许存在的。
所以,只能对工程A进行二次优化,过滤掉工程A对org.slf4j:slf4j-api:jar:1.7.21的依赖。
  • 二次优化后工程A的pom配置
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.titan</groupId>
	<artifactId>testa</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>testa</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.21</version>
			<exclusions>
				<exclusion>
					<groupId>org.slf4j</groupId>
					<artifactId>slf4j-api</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.slf4j</groupId>
				<artifactId>slf4j-api</artifactId>
				<version>1.7.25</version>
			</dependency>
		</dependencies>
	</dependencyManagement>
</project>
  • 二次优化后工程A的依赖情况

  • 二次优化后工程B的依赖情况
差点感觉自己药丸,终于通过配置工程A的pom,使工程A升级时,能够在不修改工程B的情况下,保障工程B能够使用正确的jar包。

五、总结

  • dependency manage中的配置,只对当前工程有效。(分析maven的依赖处理逻辑,首先maven会将所有的依赖进行树形管理,生成一个虚拟依赖树形结构,然后通过dependency manage对该树形依赖结构进行管理维护,生成经DM管理维护之后的树形依赖结构,如果为间接依赖,则DM无法发挥作用)
  • dependency中的exclude是可以进行传递的,当其他工程依赖某组件时,若该组件中存在exclude,那么该配置是可以被传递到此工程的。
  • 对于变更了默认依赖的组件工程,首先应该明确所需版本,因为默认版本已不适用,通过要排除掉默认版本,避免在其他工程中发生冲突。

六、延伸

  • 在持续交付过程中,很难保证开发人员在进行组件开发时,如果发生以上情况,一定会配置exclude信息;
  • 必须存在必要的校验规则,才能避免依赖该组件的工程出现包冲突,进而误用包版本的情况;
鉴于以上两点,在对组件类工程打包导入到maven私服仓库前,应该生成一个虚拟工程,引入该组件进行依赖树校验,如果发现该虚拟工程的依赖树中存在jar包版本冲突,则认为该组件类的工程jar包引入不明确,需要重新配置,通过校验后,方可打包进入到maven私服仓库中。


猜你喜欢

转载自blog.csdn.net/tearofthemyth/article/details/70217515
今日推荐