maven打包普通spring项目

前言

本文主要介绍我本人在使用maven打包一个普通spring项目使用网上各种教程都没有成功,最后多次尝试分析后成功的过程。

因为平时开发都是开发SSM、SpringBoot这一类web应用,或者为公司开发一些公共组件(导出成jar引入主项目)这样,开发控制台程序也都是使用使用基础的开发模式,建立普通的java项目然后手工导入依赖jar包,最后使用开发工具导出可执行jar包,没有接触过使用maven开发控制台程序导出jar包运行。

第一次尝试

根据自己掌握的知识点,肯定是使用maven-jar-plugin插件进行打包操作

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-jar-plugin</artifactId>
	<configuration>
		<source>1.8</source>
		<target>1.8</target>
		<archive>
			<manifest>
				<mainClass>org.test.App</mainClass>
			</manifest>
		</archive>
	</configuration>
</plugin>

执行maven package命令,没报错,去到target目录一看,输出的jar包只有十几K?这明显有问题呀,但是还是使用java -jar执行了一下报错:
在这里插入图片描述
很明显项目的依赖包没有被打包出来。于是去百度相关资料…

第二次尝试

关于maven如何打包一个普通的spring项目(输出一个执行main方法的jar包),网上很多资料是说使用maven-assembly-plugin这个插件进行打包。

第一次尝试打包使用以下配置:

<plugin>
		<artifactId>maven-assembly-plugin</artifactId>
		<configuration>
			<appendAssemblyId>false</appendAssemblyId>
			<descriptorRefs>
				<descriptorRef>jar-with-dependencies</descriptorRef>
			</descriptorRefs>
			<archive>
				<manifest>
<!-- 				此处指定main方法入口的class -->
					<mainClass>org.test.App</mainClass>
				</manifest>
			</archive>
		</configuration>
		<executions>
			<execution>
				<id>make-assembly</id>
				<phase>package</phase>
				<goals>
					<goal>assembly</goal>
				</goals>
			</execution>
		</executions>
	</plugin>

可以正常打包,但是在执行的时候出现以下错误:
在这里插入图片描述
Offending resource: class path resource [*****.xml]
于是百度相关错误,总结下来就是说执行的程序中缺少了Spring一些内置的配置文件,于是使用winRAR打开jar包查看内部的结构,发现所有的依赖jar包全部被解压成一个个class文件:

在这里插入图片描述
在这里插入图片描述
众所周知,spring内部大部分配置文件都是放在“META-INF”目录下,而且文件名称还是一样的,这些Spring的依赖包被解压后,所有的同名的内置配置文件岂不都相互覆盖了?难怪jar包执行起来报上面那个错误!

第三次尝试

于是找到新的方向:怎么使用maven-assembly-plugin插件打包出来的jar包中依赖包不被解压?

查找资料后,发现之前复制网上的pom build配置,是因为使用了maven-assembly-plugin中一个自带的配置文件,而这个配置文件中配置了打包是将所有依赖包解压!

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-assembly-plugin</artifactId>
	<configuration>
		<archive>
			<manifest>
				<mainClass>org.test.App</mainClass>
			</manifest>
		</archive>
		<!-- 这个的意思是依据一个id为“jar-with-dependencies”的配置文件内容来执行打包
		<descriptorRefs>
			<descriptorRef>jar-with-dependencies</descriptorRef>
		</descriptorRefs> -->
		<descriptors>
			<!-- 这里的意思是依据指定的配置文件进行打包 -->
			<descriptor>src/main/resource/assembly/assembly.xml</descriptor>
		</descriptors>
	</configuration>
	<executions>
		<execution>
			<id>make-assembly</id>
			<phase>package</phase>
			<goals>
				<goal>single</goal>
			</goals>
		</execution>
	</executions>
</plugin>

jar-with-dependencies执行的默认配置文件内容:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
	<id>jar-with-dependencies</id>
	<formats>
		<format>jar</format>
	</formats>
	<includeBaseDirectory>false</includeBaseDirectory>
	<dependencySets>
		<dependencySet>
			<unpack>true</unpack> <!-- 是否解压依赖jar包 --> 
			<scope>runtime</scope>
		</dependencySet>
	</dependencySets>
	<fileSets>
		<fileSet>
			<directory>${project.build.outputDirectory}</directory>
		</fileSet>
	</fileSets>
</assembly>

自定义配置文件assembly.xml:

<assembly>
	<id>with-dependence</id><!-- 配置文件的标识,同时生成的jar包名字会把这个文本包含进去 -->
	<formats>
		<format>jar</format><!-- 打包类型,此处为jar -->
	</formats>
	<includeBaseDirectory>false</includeBaseDirectory>
	<dependencySets>
		<dependencySet>
			<unpack>false</unpack><!-- 是否解压依赖jar包 -->
			<scope>runtime</scope>
		</dependencySet>
	</dependencySets>
	<fileSets>
		<fileSet>
			<directory>${project.build.outputDirectory}</directory>
			<outputDirectory>/</outputDirectory>
		</fileSet>
	</fileSets>
</assembly>

执行 maven clean package 命令进行打包,正常执行,输出的jar包也有十几兆了,我以为已经可以了!执行后还是报错:
在这里插入图片描述
我打开jar包查看了一下内部的结构,依赖jar包也都在里面:
在这里插入图片描述
为什么会执行报错找不到依赖呢?

第四次尝试

脑洞了一下,使用SpringBoot的spring-boot-maven-plugin生成可执行jar包会怎么样:

<plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
	<configuration>
		<mainClass>com.zc.largecash.cb.removeredis.App</mainClass>
	</configuration>
	<executions>
		<execution>
			<goals>
				<goal>repackage</goal>
			</goals>
		</execution>
	</executions>
</plugin>

导出的可执行jar包,可以正常运行!!!

查看了SpringBoot的spring-boot-maven-plugin生成可执行jar包内部文件结构,
然后再对比以前自己使用myeclipse导出的控制台程序,发现使用maven导出的jar包中“META-INF”下MANIFEST.MF缺少“Class-Path”!
在这里插入图片描述
于是手工编辑了MANIFEST.MF文件,将“Class-Path”加上:

Class-Path: ./a1.jar ./a2.jar ./b1.jar .........

执行,发现还是不行,结合MyEclipse导出的控制台程序中的MANIFEST.MF文件:
在这里插入图片描述
以及导出的jar包中,出现了一些eclipse的类:
在这里插入图片描述
认为应该原生的不支持读取jar包内的依赖jar包的class,于是将依赖jar包复制出来,放置在导出的可执行jar包同级目录,执行正常!

maven-jar-plugin也可以正常打包Spring普通项目

第三次尝试,与第一次使用maven-jar-plugin导出的可执行jar包,执行时出现的错误是一样的,于是回过头查看maven-jar-plugin导出的可执行jar包内的MANIFEST.MF文件,发现也是缺少“Class-Path”这一项参数的

找到maven-jar-plugin与“Class-Path”相关的资料发现:

<plugin>  
    <groupId>org.apache.maven.plugins</groupId>  
    <artifactId>maven-jar-plugin</artifactId>  
    <version>2.6</version>  
    <configuration>  
        <archive>  
            <manifest>  
                <mainClass>org.test.App</mainClass> 
                添加以下2项配置,可以使得导出的可执行jar中MANIFEST.MF文件带有“Class-Path”这一项
                <addClasspath>true</addClasspath><!-- true会在MANIFEST.MF加上Class-Path项并配置依赖包 -->
                <classpathPrefix>lib/</classpathPrefix><!-- lib/指定依赖包所在目录 -->
            </manifest>  
        </archive>  
    </configuration>  
</plugin>  

执行mevan package命令,成功,但是发现2个问题:

  1. 依赖jar包没有被导出
  2. 配置文件必须包含在导出的可执行jar包内部,不然无法被扫描到

以下为MANIFEST.MF文件内容:
在这里插入图片描述
查阅相关资料,2个问题都得以解决:

问题1. 使用maven-dependency-plugin插件,可以导出项目依赖jar包到指定目录:
<plugin>  
    <groupId>org.apache.maven.plugins</groupId>  
    <artifactId>maven-dependency-plugin</artifactId>  
    <version>2.10</version>  
    <executions>  
        <execution>  
            <id>copy-dependencies</id>  
            <phase>package</phase>  
            <goals>  
                <goal>copy-dependencies</goal>  
            </goals>  
            <configuration>  
                <outputDirectory>${project.build.directory}/lib</outputDirectory>  
            </configuration>  
        </execution>  
    </executions>  
</plugin>

这样一来,maven-jar-plugin配合使用maven-dependency-plugin就可以很好的导出可执行jar包

问题2.  
  想将配置文件放置在可执行jar包外面,很简单,只需要编辑一下MANIFEST.MF文件中“Class-Path”,添加你配置文件准备放置的位置的相对路径(或者绝对路径,绝对路径应该用的很少),如“ ./ ”则代表可执行jar包同级目录,这样就能将配置文件放在jar包可执行jar包同级目录也能被程序正常读取。
  另外需要注意,“Class-Path”配置的值中,会有很多项,各项之间一定要用空格隔开,不能使用其他字符,并且需要确保每一行不能有太多字符,及时换行,每一行最前面需要有空格!
  手工编辑MANIFEST.MF文件“Class-Path”值,毕竟还是太繁琐,每次打包都需要操作一遍,目前还没有找到maven-jar-plugin可以配置导出jar包时给MANIFEST.MF文件“Class-Path”值添加自定义信息!希望有大佬来解答一下这个问题

总结

  • maven-assembly-plugin默认配置打包会将所有依赖jar包解压,这样Spring内置的很多同名配置文件将会相互覆盖,导致输出的可执行jar包执行报:Offending resource: class path resource [*****.xml]错误
  • maven-jar-plugin无法将依赖jar包一并导出,需要配合使用maven-dependency-plugin
  • 另外附上一片介绍MANIFEST.MF文件的博文
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值