Spring如何加载XSD文件(org.xml.sax.SAXParseException: Failed to read schema document错误的解决方法)

本文原文连接: http://blog.csdn.net/bluishglc/article/details/7596118 ,转载请注明出处!

有时候你会发现过去一直启动正常的系统,某天启动时会报出形如下面的错误:

 

org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'http://www.springframework.org/schema/beans/spring-beans-2.0.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.


很显然,spring xml配置文件中指定的xsd文件读取不到了,原因多是因为断网或spring的官网暂时无法连接导致的。 你可以通过在浏览器输入xsd文件的URL,如:http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 进行确认。

 

 

关于这个问题,网上有两种常见的解决方法,第一种简单有效,但是工作量大,即:把所有spring配置文件中url形式的xsd路径转换成指向本地xsd文件的classpath形式的路径,例如:classpath:org/springframework/beans/factory/xml/spring-beans-2.5.xsd ,再有一种方法就是在本机搭建web服务器,按URL创建相应文件夹,放入对应xsd文件,在本机hosts文件中加入"127.0.0.1 www.springframework.org".实际上,这两种方法都属于“歪打正着”式的方法,直正弄明白这一问题还需要从spring的XSD文件加载机制谈起。

 

首先:你必须知道一点:spring在加载xsd文件时总是先试图在本地查找xsd文件(spring的jar包中已经包含了所有版本的xsd文件),如果没有找到,才会转向去URL指定的路径下载。这是非常合理的做法,并不像看上去的那样,每次都是从站点下载的。事实上,假如你的所有配置是正确定的,你的工程完全可以在断网的情况下启动而不会报上面的错误。Spring加载xsd文件的类是PluggableSchemaResolver,你可以查看一下它的源码来验证上述说法。另外,你可以在log4j.xml文件中加入:

<logger name="org.springframework.beans.factory.xml">

<level value="all" />

</logger>

通过日志了解spring是何加载xsd文件的。

 

 

接下来,问题就是为什么spring在本地没有找到需要的文件,不得不转向网站下载。关于这个问题,其实也非常简单。在很多spring的jar包里,在META-INF目录下都有一个spring.schemas,这是一个property文件,其内容类似于下面:

http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd

http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd

http\://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd

....


实际上,这个文件就是spring关于xsd文件在本地存放路径的映射,spring就是通过这个文件在本地(也就是spring的jar里)查找xsd文件的。那么,查找不到的原因排除URL输入有误之外,可能就是声明的xsd文件版本在本地不存在。一般来说,新版本的spring jar包会将过去所有版本(应该是自2.0以后)的xsd打包,并在spring.schemas文件中加入了对应项,出现问题的情况往往是声明使用了一个高版本的xsd文件,如3.0,但依赖的spring的jar包却是2.5之前的版本,由于2.5版本自然不可能包含3.0的xsd文件,此时就会导致spring去站点下载目标xsd文件,如遇断网或是目标站点不可用,上述问题就发生了。

 

 

但是,在实现开发中,出现上述错误的几率并不高,最常见的导致这一问题的原因其实与使用了一个名为“assembly”的maven打包插件有关。很多项目需要将工程连同其所依赖的所有jar包打包成一个jar包,maven的assembly插件就是用来完成这个任务的。但是由于工程往往依赖很多的jar包,而被依赖的jar又会依赖其他的jar包,这样,当工程中依赖到不同的版本的spring时,在使用assembly进行打包时,只能将某一个版本jar包下的spring.schemas文件放入最终打出的jar包里,这就有可能遗漏了一些版本的xsd的本地映射,进而出现了文章开始提到的错误。如果你的项目是打成单一jar的,你可以通过检查最终生成的jar里的spring.schemas文件来确认是不是这种情况。而关于这种情况,解决的方法一般是推荐使用另外一种打包插件shade,它确实是一款比assembly更加优秀的工具,在对spring.schemas文件处理上,shade能够将所有jar里的spring.schemas文件进行合并,在最终生成的单一jar包里,spring.schemas包含了所有出现过的版本的集合!

 

以上就是spring加载XSD文件的机制和出现问题的原因分析。实际上,我们应该让我们工程在启动时总是加载本地的xsd文件,而不是每次去站点下载,做到这一点就需要你结合上述提及的种种情况对你的工程进行一番检查。

 

 

#评论:
stan503: 
    引用“oDDiaoDeHuaLi”的评论:
    第一种情况,直接把xsd的版本号去掉
    看jar包的schemas就能知道不加版本号对应的就是jar包的版本号..                 http\://www.springframework.org/schema/context/spring-context-    3.1.xsd=org/springframework/context/config/spring-context-3.1.xsd     http\://www.springframework.org/schema/context/spring-    context.xsd=org/springframework/context/config/spring-context-3.1.xsd(06-13 22:57#29楼)

DropOfJupiter: 
    写的很清楚,我本地使用的spring版本是4.1.1的,我看了spring-context-4.1.1.RELEASE.jar下的            spring.schemas文件,发现里面的xsd文件是从4.1-2.5的,而我在spring配置文件中加载的是3.0。结果发现我    这边还真是因为断网的原因导致的这个错误提示,谢谢博主(04-20 16:17#28楼)

fareeraliens: 
    引用“leonzhouwei”的评论:
    主要是需要在&lt;transformers&gt;里面加上下面内容 : &lt;transform...
    [reply]leonzhouwei[/reply] 确实是这样,这样配置maven-shade-plugin以后查看构建产出的jar包,    发现spring.schemas和spring.handlers都正确了。 并且在无外网的环境下能正常启动Spring。(02-26 02:21#19楼)举报回复
carl3025
carl3025: 直接从本地jar包中导入相应的定义文件,就可以避免报错了,不联网也可以正常使用了(11-05 15:05#18楼)

xiaosheng_papa: 
    我用的是spring3.01版本,在本地配置了spring-beans-3.0.xsd了,为什么还报这个错 org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'http://www.springframework.org/schema/beans/spring-beans-3.0.xsd?', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.(06-28 11:08#12楼)

Allen_: 
    我配置了spring-aop-3.0.xsd的路径,还是报错:Failed to read schema document 'http://www.springframework.org/schema/beans/spring-aop-3.0.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.(12-26 20:54#11楼)

lutinghuan: 
那么,查找不到的原因排除URL输入有误之外,可能就是声明的xsd文件版本在本地不存在。一般来说,新版本的spring jar包会将过去所有版本(应该是自2.0以后)的xsd打包,并在spring.schemas文件中加入了对应项,出现问题的情况往往是声明使用了一个高版本的xsd文件,如3.0,但依赖的spring的jar包却是2.5之前的版本,由于2.5版本自然不可能包含3.0的xsd文件,此时就会导致spring去站点下载目标xsd文件,如遇断网或是目标站点不可用,上述问题就发生了。 ------------------------------------------------------------------- 楼主,这个问题还是很容易产生的呢。比如COPY别人高版本的配置,就会导致引用跟当前版本不一样。我就是这一类,多谢了。(12-10 16:16#10楼)


鲸息_Leon: 
    主要是需要在<transformers>里面加上下面内容 : <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.handlers</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.schemas</resource> </transformer>(08-14 20:10#9楼)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值