前言
最近要把之前寫好的監控系統加上報警功能,就是通過rpc調用發短信發郵件的服務發送報警信息。發短信發郵件的功能是通過dubbo管理提供的。自然使用這些服務就難免用到spring。而我這又是一個storm工程,為了方便,我都是用maven-shade-plugin把所有依賴的jar打到一起。
在本地運行沒有任何問題,但已提交到在線環境的storm(在線環境是沒法連接到外網的),就會報錯:
spring cvc-elt.1: Cannot find the declaration of element 'beans'
對於這個錯誤,網上有很多解決方法,其本質就是找不到對應的xsd文件。但好多解決方法都是碰巧並不是對問題本質有了了解后的解決方式。所以我在這里記錄下自己的解決方式。
spring加載xsd文件的流程
要解決上述問題,就需要理解spring加載xsd文件的流程:
1、spring首先會讀取spring jar包下META-INF下的spring.schemas,根據spring.schemas里的映射路徑在本地找xsd文件。
2、如果在本地找不到xsd文件,spring會通過配置文件里的url到官網上下載xsd文件。
發生問題的原因
通過上述加載xsd的流程,已改可以預見發生問題的原因:
1、在不能訪問外網的情況下,使用的xsd的版本高於使用的spring的版本,spring jar包里沒有對應版本的xsd導致
2、在不能訪問外網的情況下,jar包的META-INF目錄下的spring.schemas被破壞,沒法找到xsd的映射路徑
知道了上述這些之后,我打開了我用maven-shade-plugin打好的jar包,找到META-INF下的spring.schemas,發下里邊的映射路徑果然不全。掐指一算就知道是maven-shade-plugin打包的問題,它沒有將各個jar包里的spring.schemas內容合並到一起,而是采用了覆蓋的方式。知道了這個原因后,在maven-shade-plugin里配置如下:
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.schemas</resource> </transformer>
然后就這樣完美解決了。
據說使用maven-assembly-plugin打包也會出現此問題,所以要當心了