适用场景

在项目中遇到需求,根据不同省份需要依赖不同的jar包执行相同逻辑。由于不同省份jar包不同,且存在同一jar包不同版本,导致高版本覆盖低版本的问题,同时为缩减项目包的大小。所以希望将这部分jar包通过外部引入的方式在运行时动态加载而非放入可执行jar包的libs目录下。这样项目分省部署只需依赖相关省份的jar包即可。

出现问题

基于此,根据maven的scope作用域(可参见之前博文),使用<scope>provideded</scope>对这部分分省的jar包进行修饰。使系统通过编译,同时在执行时,根据省份不同以嵌入式的方式加载不同jar包。
但是发现<scope>provideded</scope>修饰的jar在项目被打成可执行jar包时仍然会被打包到项目jar包的libs目录中。后来发现<scope>provideded</scope>修饰的jar包在打成war包这种依赖容器(tomcat)执行的文件格式时时是不会被打包到libs目录中去的,但是打成可执行jar时不会起作用。

解决方法

使用spring-boot-maven-plugin插件将相关jar从libs移除,同时使用java -loader.path=jar包文件夹 -jar xxx.jar方式在执行时动态引用。

maven jar包打不进去 maven打jar包代码没变_spring-boot

spring-boot-maven-plugin的repackage指令可以将基于Spring构建的项目打成一个完整的可执行jar包,使其可以通过命令行,以java -jar的方式执行。其在打包过程中加入org.springframework.boot.loader,为基于Spring构建的项目添加引导(执行入口)。

基于spring-boot-maven-plugin解决本文问题。
pom.xml中添加:

<build>
		<finalName>manage</finalName>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<mainClass>com.czx.manage.App</mainClass>  <!-- 项目main方法所在类 -->
					<layout>ZIP</layout>   <!--  必填项,指定org.springframework.boot.loader使用的种类 -->
					<excludes>
						<exclude>
							<groupId>com.xxxx</groupId>
							<artifactId>xxxx</artifactId>   <!--  不希望打包到libs目录下的jar包 -->
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

这样在执行mvn package命令时,相关jar包不会被打到libs目录中。

spring boot maven plugin layout(spring-boot-maven-plugin layout)参数分析

spring-boot-maven-plugin官网对layout属性的陈述并不好理解。通过分析和实验发现其主要作用是指定项目启动的Main-Class的org.springframework.boot.loader的类型。其主要有JAR, WAR, ZIP, DIR, NONE 5中类型。默认是JAR类型。
通过观察打包后保存jar描述信息的MANIFEST.MF文件可以得知其对应关系:

  • 不指定,默认
  • JAR
  • WAR
  • ZIP和DIR
  • NONE(打不可执行jar包)
    如果要使用java -loader.path=jar包文件夹 -jar xxx.jar以嵌入式的方式,在程序运行时引用外部jar包,需要指定org.springframework.boot.loader的类型为org.springframework.boot.loader.PropertiesLauncher。即使用DIR或ZIP方式。
    如果项目以war包形式运行而非jar包形式,可以使用maven的scope设为provided的方式。若要以可执行jar包的方式运行,若需要适用这类场景,可参考本文实现方式。