一次Spring项目打包问题排查的实战记录
一个Spring项目,打成jar包之后运行,在有网络的时候是正常的,但是一旦无网络就会报错,具体是怎么回事呢?这篇文章就来记录下这次问题排查经过。
背景介绍
一个图形化的界面,带本地数据库,要求可以在无网络环境下运行,我帮朋友用的Java写的图形化界面,虽然不是很美观,但是胜在熟悉Java。
项目使用的是idea的「BuildArtifacts」打包,打包之后运行正常,界面和数据库访问都正常,最开始报过几次错,后来就没出现了,也没找到原因,就先那样了。
后来发给别人了,完全打不开,跟之前的报错一样,看来必须要搞清楚报错的原因了。
问题排查
报错内容
首先贴一下报错的信息:
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException:
Line8inXMLdocumentfromclasspathresource[spring.xml]isinvalid;
nestedexceptionisorg.xml.sax.SAXParseException;
lineNumber:8;columnNumber:76;
cvc-elt.1:找不到元素'beans'的声明。
spring.xml代码截取如下:
问题复现
因为我之前也碰到过这个报错,所以想着复现一下问题,方便排查。
我直接在虚拟机中运行,无论是覆盖安装还是卸载再次安装都没问题,我就想可能是环境问题导致的吧,就想着装一个新的虚拟机试一下。
新系统装完之后,一运行,果然崩溃了,报错信息一样。能复现问题,可以说为解决问题开了个好头。
问题排查
找到原因
通过关键字cvc-elt.1:找不到元素'beans'的声明开始搜索,搜索到的结果基本都是以下的内容。
配置文件头部配置的xsd版本信息不正确,造成解析时出错。spring头部xsd或dtd校验文件的查找分两步,第一先从本地jar包中找,如果找到则用本地jar包的进行校验(可以在spring-beans.jar或spring-context.jar里的META-INF下的spring.schemas文件中找到xsd文件位置的定义),如果没有找到则进行第二步查找,它会尝试从网络中下载该文件然后校验,如果系统断网或下载不下来,则会抛出上述异常。
照着这个思路,朋友也提醒我,看下虚拟机的系统是否联网了,我一看,果然没联网,赶紧联网测试发现能正常运行,问题的原因找到了。
再次困惑
找到了问题原因,好像就马上就能解决了,但事实并不是我想的那样。
网上的解决办法是:
将applicationContext.xml中xsd文件定义的版本改为springjar包中定义的xsd的版本,如果版本定义的太高在本地会无法找到,只能从网络上下载。
但是,查看spring-beans.jar里META-INF下的spring.schemas文件,发现无论版本号是多少,最后指向的都是一个。
截取了部分代码如下:
http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans.xsd http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans.xsd http\://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans.xsd http\://www.springframework.org/schema/beans/spring-beans-3.1.xsd=org/springframework/beans/factory/xml/spring-beans.xsd http\://www.springframework.org/schema/beans/spring-beans-3.2.xsd=org/springframework/beans/factory/xml/spring-beans.xsd http\://www.springframework.org/schema/beans/spring-beans-4.0.xsd=org/springframework/beans/factory/xml/spring-beans.xsd http\://www.springframework.org/schema/beans/spring-beans-4.1.xsd=org/springframework/beans/factory/xml/spring-beans.xsd http\://www.springframework.org/schema/beans/spring-beans-4.2.xsd=org/springframework/beans/factory/xml/spring-beans.xsd http\://www.springframework.org/schema/beans/spring-beans-4.3.xsd=org/springframework/beans/factory/xml/spring-beans.xsd http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans.xsd
后来又搜到一篇文章「spring5之SAXParseException:cvc-elt.1:找不到元素“beans”的声明[1]」,说Spring5之后就不需要写版本号了。
那跟我看到的情况是一样的,确实各个版本号指向的都是同一个,看来不是版本号的问题,那到底是怎么回事?
一波三折
既然xsd的版本没错,那问题出在哪里呢?
继续搜索之后,看到了这篇文章「系统启动时,spring配置文件解析失败,报”cvc-elt.1:找不到元素'beans'的声明“异常[2]」。
打包之后,spring.schemas位于jar包的META-INF目录下,但是spring.schemas里并没有spring-beans.xsd,看来问题是在这了,我仿照作者的方法,把上面提到的spring-beans.jar里META-INF下的spring.schemas里的关于spring-beans.xsd的部分添加到了压缩包的spring.schemas里。
重新打包之后仍然报错,但是报的错不是之前的错了,是说我的主函数类找不到了,真的是让人摸不着头脑,情况类似啊,为什么我的不好使。
豁然开朗
还是上面的操作,我让朋友试了一下,他测试之后居然好使!
我问他怎么操作的,他说跟我的操作一样,只不过把https部分的也加上了,我心想不应该啊,也没引用https的spring-beans.xsd,不应该是这个问题吧。
我按照他的操作,在我电脑上重新打包,发现还是不好使;我又把他给我的文件替换到我打的包里,还是不好使。真的是蒙了,操作是一样的,为什么我的不好使。
后来朋友说让我把修改好的包发给他,他看了之后发现我打的包大小不一样,正常应该是14MB,但是我的包是500KB,我又重新操作了一遍,发现我把文件替换之后,整个jar包的大小变小了,原来是我的压缩包软件有问题。
朋友的电脑是Windows,是直接用WinRAR打开jar包,然后把文件替换;我的是Mac,用的eZip软件打开jar包,然后替换文件。最后,我使用虚拟机按照朋友的操作测试后发现ok了。
谁能料到是压缩软件的问题呢?但是也不能全怪软件,毕竟人家是解压缩软件,并不是专门处理jar文件的。
完美解决
虽然找到了问题原因,也有了解决办法,但是解决的办法却不够好,总不能每次打好包再手动替换文件吧?
我觉得既然我们能遇到的问题,肯定也有其他人遇到,我就使用关键字spring.schemas打包之后没有把beans打进去进行了搜索,发现了完美的解决方案:「spring打包到jar问题[3]」。
问题的根本原因是,由于spring多个jar包都包含spring.schemas,「BuildArtifacts」和「Maven」默认打包只会把第一次遇到的schemas文件打入jar包。
解决办法是使用mavenshade打包,具体的代码如下:
org.apache.maven.plugins maven-shade-plugin 3.2.2 package shade xxx.xxx.xxx.App META-INF/spring.handlers META-INF/spring.schemas META-INF/spring.tooling
将代码放在项目pom.xml的
感受
问题解决了,从中也得到一些感受:
•遇到问题还是得尽快解决,因为问题是不会放过你的。
•Mac下的压缩软件暂时没有Windows下的好使。
•网上的答案真的是千篇一律,都是一个人的答案被很多人复制,而且没有讲清楚问题。
•搜到的千篇一律的答案,可能已经过时了,并不适合自己的情况。
•自己遇到的问题,绝大部分都是别人遇到过的,是可以解决的,耐心搜索就会找到解决办法。
引用链接
[1]spring5之SAXParseException:cvc-elt.1:找不到元素“beans”的声明
[2]系统启动时,spring配置文件解析失败,报”cvc-elt.1:找不到元素'beans'的声明“异常
[3]spring打包到jar问题
总结
到此这篇关于一次Spring项目打包问题排查的文章就介绍到这了,更多相关Spring项目打包问题排查内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。