Spring加載XSD文件發(fā)生錯(cuò)誤的解決方法
有時(shí)候你會(huì)發(fā)現(xiàn)過(guò)去一直啟動(dòng)正常的系統(tǒng),某天啟動(dòng)時(shí)會(huì)報(bào)出形如下面的錯(cuò)誤:
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文件讀取不到了,原因多是因?yàn)閿嗑W(wǎng)或spring的官網(wǎng)暫時(shí)無(wú)法連接導(dǎo)致的。 你可以通過(guò)在瀏覽器輸入xsd文件的URL,如:http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 進(jìn)行確認(rèn)。
關(guān)于這個(gè)問(wèn)題,網(wǎng)上有兩種常見(jiàn)的解決方法,第一種簡(jiǎn)單有效,但是工作量大,即:把所有spring配置文件中url形式的xsd路徑轉(zhuǎn)換成指向本地xsd文件的classpath形式的路徑
例如:classpath:org/springframework/beans/factory/xml/spring-beans-2.5.xsd ,再有一種方法就是在本機(jī)搭建web服務(wù)器,按URL創(chuàng)建相應(yīng)文件夾,放入對(duì)應(yīng)xsd文件,在本機(jī)hosts文件中加入"127.0.0.1 www.springframework.org".實(shí)際上,這兩種方法都屬于“歪打正著”式的方法,直正弄明白這一問(wèn)題還需要從spring的XSD文件加載機(jī)制談起。
首先:你必須知道一點(diǎn):spring在加載xsd文件時(shí)總是先試圖在本地查找xsd文件(spring的jar包中已經(jīng)包含了所有版本的xsd文件),如果沒(méi)有找到,才會(huì)轉(zhuǎn)向去URL指定的路徑下載。
這是非常合理的做法,并不像看上去的那樣,每次都是從站點(diǎn)下載的。事實(shí)上,假如你的所有配置是正確定的,你的工程完全可以在斷網(wǎng)的情況下啟動(dòng)而不會(huì)報(bào)上面的錯(cuò)誤。Spring加載xsd文件的類(lèi)是PluggableSchemaResolver,你可以查看一下它的源碼來(lái)驗(yàn)證上述說(shuō)法。另外,你可以在log4j.xml文件中加入:
<logger name="org.springframework.beans.factory.xml"> <level value="all" /> </logger>
通過(guò)日志了解spring是何加載xsd文件的。
接下來(lái),問(wèn)題就是為什么spring在本地沒(méi)有找到需要的文件,不得不轉(zhuǎn)向網(wǎng)站下載。關(guān)于這個(gè)問(wèn)題,其實(shí)也非常簡(jiǎn)單。在很多spring的jar包里,在META-INF目錄下都有一個(gè)spring.schemas,這是一個(gè)property文件,其內(nèi)容類(lèi)似于下面:
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 ....
實(shí)際上,這個(gè)文件就是spring關(guān)于xsd文件在本地存放路徑的映射,spring就是通過(guò)這個(gè)文件在本地(也就是spring的jar里)查找xsd文件的。那么,查找不到的原因排除URL輸入有誤之外,可能就是聲明的xsd文件版本在本地不存在。
一般來(lái)說(shuō),新版本的spring jar包會(huì)將過(guò)去所有版本(應(yīng)該是自2.0以后)的xsd打包,并在spring.schemas文件中加入了對(duì)應(yīng)項(xiàng),出現(xiàn)問(wèn)題的情況往往是聲明使用了一個(gè)高版本的xsd文件,如3.0,但依賴(lài)的spring的jar包卻是2.5之前的版本,由于2.5版本自然不可能包含3.0的xsd文件,此時(shí)就會(huì)導(dǎo)致spring去站點(diǎn)下載目標(biāo)xsd文件,如遇斷網(wǎng)或是目標(biāo)站點(diǎn)不可用,上述問(wèn)題就發(fā)生了。
但是,在實(shí)現(xiàn)開(kāi)發(fā)中,出現(xiàn)上述錯(cuò)誤的幾率并不高,最常見(jiàn)的導(dǎo)致這一問(wèn)題的原因其實(shí)與使用了一個(gè)名為“assembly”的maven打包插件有關(guān)。很多項(xiàng)目需要將工程連同其所依賴(lài)的所有jar包打包成一個(gè)jar包,maven的assembly插件就是用來(lái)完成這個(gè)任務(wù)的。
但是由于工程往往依賴(lài)很多的jar包,而被依賴(lài)的jar又會(huì)依賴(lài)其他的jar包,這樣,當(dāng)工程中依賴(lài)到不同的版本的spring時(shí),在使用assembly進(jìn)行打包時(shí),只能將某一個(gè)版本jar包下的spring.schemas文件放入最終打出的jar包里,這就有可能遺漏了一些版本的xsd的本地映射,進(jìn)而出現(xiàn)了文章開(kāi)始提到的錯(cuò)誤。
如果你的項(xiàng)目是打成單一jar的,你可以通過(guò)檢查最終生成的jar里的spring.schemas文件來(lái)確認(rèn)是不是這種情況。而關(guān)于這種情況,解決的方法一般是推薦使用另外一種打包插件shade,它確實(shí)是一款比assembly更加優(yōu)秀的工具,在對(duì)spring.schemas文件處理上,shade能夠?qū)⑺衘ar里的spring.schemas文件進(jìn)行合并,在最終生成的單一jar包里,spring.schemas包含了所有出現(xiàn)過(guò)的版本的集合!
以上就是spring加載XSD文件的機(jī)制和出現(xiàn)問(wèn)題的原因分析。實(shí)際上,我們應(yīng)該讓我們工程在啟動(dòng)時(shí)總是加載本地的xsd文件,而不是每次去站點(diǎn)下載,做到這一點(diǎn)就需要你結(jié)合上述提及的種種情況對(duì)你的工程進(jìn)行一番檢查。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- SpringBoot使用CXF集成WebService的方法
- SpringBoot2.x 整合Spring-Session實(shí)現(xiàn)Session共享功能
- SpringCloud中的斷路器(Hystrix)和斷路器監(jiān)控(Dashboard)
- 詳解springcloud 基于feign的服務(wù)接口的統(tǒng)一hystrix降級(jí)處理
- SpringBoot通過(guò)yml和xml文件配置日志輸出方法
- Linux編輯啟動(dòng)、停止與重啟springboot jar包腳本實(shí)例
- Spring Boot Excel文件導(dǎo)出下載實(shí)現(xiàn)代碼
相關(guān)文章
Java中常用阻塞隊(duì)列的問(wèn)題小結(jié)
這篇文章主要介紹了Java常用阻塞隊(duì)列問(wèn)題,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01一篇文章帶你玩轉(zhuǎn)Spring bean的終極利器
這篇文章主要給大家介紹了關(guān)于玩轉(zhuǎn)Spring bean的終極利器的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring bean具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05Spring注解@Configuration和@Component區(qū)別詳解
@Component和@Configuration都可以作為配置類(lèi),之前一直都沒(méi)覺(jué)得這兩個(gè)用起來(lái)有什么差別,可能有時(shí)程序跑的和自己想的有所區(qū)別也沒(méi)注意到,下面這篇文章主要給大家介紹了關(guān)于Spring注解@Configuration和@Component區(qū)別的相關(guān)資料,需要的朋友可以參考下2023-04-04Java使用FilenameFilter查找出目錄下指定后綴的文件示例
這篇文章主要介紹了Java使用FilenameFilter查找出目錄下指定后綴的文件,結(jié)合實(shí)例形式分析了java基于FilenameFilter類(lèi)的文件遍歷、查找相關(guān)操作技巧,需要的朋友可以參考下2019-10-10Java中的MarkerFilter的應(yīng)用場(chǎng)景及使用示例詳解
這篇文章主要介紹了Java中的MarkerFilter的應(yīng)用場(chǎng)景及使用示例詳解,使用log4j2,負(fù)責(zé)從消息隊(duì)列收集日志的,現(xiàn)在系統(tǒng)收集到的日志能和這個(gè)系統(tǒng)本身的日志分開(kāi),需要的朋友可以參考下2024-01-01Spring與Struts整合之使用自動(dòng)裝配操作示例
這篇文章主要介紹了Spring與Struts整合之使用自動(dòng)裝配操作,結(jié)合實(shí)例形式詳細(xì)分析了Spring與Struts整合使用自動(dòng)裝配具體操作步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2020-01-01java 用redisTemplate 的 Operations存取list集合操作
這篇文章主要介紹了java 用redisTemplate 的 Operations存取list集合操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08JAVA實(shí)現(xiàn)簡(jiǎn)單搶紅包算法(模擬真實(shí)搶紅包)
這篇文章主要介紹了JAVA實(shí)現(xiàn)簡(jiǎn)單搶紅包算法(模擬真實(shí)搶紅包)的實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-12-12