天天看點

為什麼在Spring的配置裡,最好不要配置xsd檔案的版本号 Spring core Spring Security Spring integration

這篇blog源于一個疑問:

我們公司使了阿裡的dubbo,但是阿裡的開源網站http://code.alibabatech.com,挂掉有好幾個月了,為什麼我們的應用啟動沒有問題?

我們的應用的spring配置檔案裡有類似的配置:

我們都知道spring在啟動時是要檢驗xml檔案的。或者為什麼在eclipse裡xml沒有錯誤提示?

比如這樣的一個spring配置:

我們也可以在後面加上版本号:

有這個版本号和沒有有什麼差別呢?

首先來看下xml的一些概念:

xml的schema裡有namespace,可以給它起個别名。比如常見的spring的namespace:

通常情況下,namespace對應的uri是一個存放xsd的位址,盡管規範沒有這麼要求。如果沒有提供schemalocation,那麼spring的xml解析器會從namespace的uri裡加載xsd檔案。我們可以把配置檔案改成這個樣子,也是可以正常工作的:

schemalocation提供了一個xml namespace到對應的xsd檔案的一個映射,是以我們可以看到,在xsi:schemalocation後面配置的字元串都是成對的,前面的是namespace的uri,後面是xsd檔案的uri。比如:

spring預設在啟動時是要加載xsd檔案來驗證xml檔案的,是以如果有的時候斷網了,或者一些開源軟體切換域名,那麼就很容易碰到應用啟動不了。我記得當時oracle收購sun公司時,遇到過這個情況。

為了防止這種情況,spring提供了一種機制,預設從本地加載xsd檔案。打開spring-context-3.2.0.release.jar,可以看到裡面有兩個特别的檔案:

spring.handlers

spring.schemas

再打開jar包裡的org/springframework/context/config/ 目錄,可以看到下面有

spring-context-2.5.xsd

spring-context-3.0.xsd

spring-context-3.1.xsd

spring-context-3.2.xsd

很明顯,可以想到spring是把xsd檔案放到本地了,再在spring.schemas裡做了一個映射,優先從本地裡加載xsd檔案。

并且spring很貼心,把舊版本的xsd檔案也全放了。這樣可以防止更新了spring版本,而配置檔案裡用的還是舊版本的xsd檔案,然後斷網了,應用啟動不了。

我們還可以看到,在沒有配置版本号時,用的就是目前版本的xsd檔案:

同樣,我們打開dubbo的jar包,可以在它的spring.schemas檔案裡看到有這樣的配置:

是以,spring在加載dubbo時,會從dubbo的jar裡加載dubbo.xsd。

可以用這樣的方式來跳過校驗:

可以參考spring的文檔,實際上是相當簡單的。隻要實作自己的namespacehandler,再配置一下spring.handlers和spring.schemas就可以了。

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/extensible-xml.html

http://hellojava.info/?p=135

http://stackoverflow.com/questions/11174286/spring-xml-namespaces-how-do-i-find-what-are-the-implementing-classes-behind-t

<code>aop</code> - <code>aopnamespacehandler</code>

<code>c</code> - <code>simpleconstructornamespacehandler</code>

<code>cache</code> - <code>cachenamespacehandler</code>

<code>context</code> - <code>contextnamespacehandler</code>

<code>jdbc</code> - <code>jdbcnamespacehandler</code>

<code>jee</code> - <code>jeenamespacehandler</code>

<code>jms</code> - <code>jmsnamespacehandler</code>

<code>lang</code> - <code>langnamespacehandler</code>

<code>mvc</code> - <code>mvcnamespacehandler</code>

<code>oxm</code> - <code>oxmnamespacehandler</code>

<code>p</code> - <code>simplepropertynamespacehandler</code>

<code>task</code> - <code>tasknamespacehandler</code>

<code>tx</code> - <code>txnamespacehandler</code>

<code>util</code> - <code>utilnamespacehandler</code>

<code>security</code> - <code>securitynamespacehandler</code>

<code>oauth</code> - <code>oauthsecuritynamespacehandler</code>

<code>int</code> - <code>integrationnamespacehandler</code>

<code>amqp</code> - <code>amqpnamespacehandler</code>

<code>event</code> - <code>eventnamespacehandler</code>

<code>feed</code> - <code>feednamespacehandler</code>

<code>file</code> - <code>filenamespacehandler</code>

<code>ftp</code> - <code>ftpnamespacehandler</code>

<code>gemfire</code> - <code>gemfireintegrationnamespacehandler</code>

<code>groovy</code> - <code>groovynamespacehandler</code>

<code>http</code> - <code>httpnamespacehandler</code>

<code>ip</code> - <code>ipnamespacehandler</code>

<code>jmx</code> - <code>jmxnamespacehandler</code>

<code>mail</code> - <code>mailnamespacehandler</code>

<code>redis</code> - <code>redisnamespacehandler</code>

<code>rmi</code> - <code>rminamespacehandler</code>

<code>script</code> - <code>scriptnamespacehandler</code>

<code>security</code> - <code>integrationsecuritynamespacehandler</code>

<code>sftp</code> - <code>sftpnamespacehandler</code>

<code>stream</code> - <code>streamnamespacehandler</code>

<code>twitter</code> - <code>twitternamespacehandler</code>

<code>ws</code> - <code>wsnamespacehandler</code>

<code>xml</code> - <code>integrationxmlnamespacehandler</code>

<code>xmpp</code> - <code>xmppnamespacehandler</code>

為什麼不要在spring的配置裡,配置上xsd的版本号?

因為如果沒有配置版本号,取的就是目前jar裡的xsd檔案,減少了各種風險。

而且這樣約定大于配置的方式很優雅。

http://stackoverflow.com/questions/10768873/spring-di-applicationcontext-xml-how-exactly-is-xsischemalocation-used