- <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd">
當我們用DOM或者Digester來解析這個XML的時候,如果當前計算機已聯網那麼解析的速度比較慢,如果當前計算機未聯網則會報無法連接主機 的異常。這是因爲XML的解析器需要讀取dtd的內容,而這個dtd文件是存在於互聯網的某臺主機上的.
讓我們看看開源框架是如何驗證DTD的:
Spring如何解析網絡和本地dtd配置的路徑
- /**
- * EntityResolver implementation for the Spring beans DTD,
- * to load the DTD from the Spring class path (or JAR file).
- *
- * <p>Fetches "spring-beans-2.0.dtd" from the class path resource
- * "/org/springframework/beans/factory/xml/spring-beans-2.0.dtd",
- * no matter whether specified as some local URL that includes "spring-beans"
- * in the DTD name or as "http://www.springframework.org/dtd/spring-beans-2.0.dtd".
- *
- * @author Juergen Hoeller
- * @author Colin Sampaleanu
- * @since 04.06.2003
- * @see ResourceEntityResolver
- */
配置dtd從源代碼路徑,不管是否有特殊的本地url包含spring-beans.dtd的名稱 ,實際還是從本地取DTD路徑.[ XML配置還是以網絡地址顯示],這也是爲什麼即使Spring在沒有網絡連接的情況下還是依然可以運行.
那麼這是怎麼查找指定的,請看如下代碼:
Java代碼
public InputSource resolveEntity(String publicId, String systemId)
通過publicId和systemId
比如:
其PublicID就是-//SPRING//DTD BEAN//EN.
其 SystemID就是- http://www.springframework.org/dtd/spring-beans.dtd.
在Spring框架中只要你使用標準的xml dtd或者schema聲名,就會自動從spring.jar裏面加載到dtd或schema.其加載程序如下.
- Resource resource = new ClassPathResource(dtdFile, getClass());
- InputSource source = new InputSource(resource.getInputStream());
- source.setPublicId(publicId);
- source.setSystemId(systemId);
這裏的路徑就是相對於此BeansDtdResolver的路徑,也就是org.springframework.beans.factory.xml,所以Spring的dtd等配置文件放在這個目錄下,沒有網絡照樣運行.
接下來讓我們看下Struts是如何加載dtd文件的.
- protected String[] registrations =
- {
- "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN",
- "/org/apache/struts/resources/struts-config_1_0.dtd",
- "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN",
- "/org/apache/struts/resources/struts-config_1_1.dtd",
- "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN",
- "/org/apache/struts/resources/struts-config_1_2.dtd",
- "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN",
- "/org/apache/struts/resources/struts-config_1_3.dtd",
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",
- "/org/apache/struts/resources/web-app_2_3.dtd"
- };
publicID直接寫死,systemId直接寫死.哈哈,與Spring對比,Spring的publicId由xml動態指定,如果需要添加dtd或schema版本等不需要修改代碼,Struts必須修改代碼,或許大家也看到差距了,感覺Struts1.X都很久沒更久了,曾經的輝煌都被埋沒了.[不知道哪種利益驅動了,搞了個struts2.x,完全不同的理念]
- // Create a new Digester instance with standard capabilities
- configDigester = new Digester();
- configDigester.setNamespaceAware(true);
- configDigester.setValidating(this.isValidating());
- configDigester.setUseContextClassLoader(true);
- configDigester.addRuleSet(new ConfigRuleSet());
- for (int i = 0; i < registrations.length; i += 2) {
- URL url = this.getClass().getResource(registrations[i + 1]);
- if (url != null) {
- configDigester.register(registrations[i], url.toString());
- }
- }
- this.addRuleSets();
Struts是使用Digester進行dtd的註冊,現在終於明白了,爲什麼Struts和Spring在沒有網絡的情況下可以運行,但是有的外部包,在沒有網絡的情況下,或者網絡有問題的時候會出問題,這也是我們要注意的,在引入其他項目時,配置文件中的dtd是必須要關注的,在本地開發完全正常,到沒有網絡環境的時候,你就傻眼了.
解決Dtd問題也是我們平時開發必須考慮的.