Spring,Struts的DTD驗證

 一般比較正式的XML信息中都會包含對應的DTD聲明,用來定義 該XML文檔中的格式,例如WEB項目中用到的web.xml,例如struts的配置文件struts-config.xml,下面是web.xml中 用到的DTD信息:
  1. <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"    
  2.        "http://java.sun.com/dtd/web-app_2_3.dtd">  

當我們用DOM或者Digester來解析這個XML的時候,如果當前計算機已聯網那麼解析的速度比較慢,如果當前計算機未聯網則會報無法連接主機 的異常。這是因爲XML的解析器需要讀取dtd的內容,而這個dtd文件是存在於互聯網的某臺主機上的.
讓我們看看開源框架是如何驗證DTD的:
Spring如何解析網絡和本地dtd配置的路徑

Java代碼
  1. /**  
  2.  * EntityResolver implementation for the Spring beans DTD,  
  3.  * to load the DTD from the Spring class path (or JAR file).  
  4.  *  
  5.  * <p>Fetches "spring-beans-2.0.dtd" from the class path resource  
  6.  * "/org/springframework/beans/factory/xml/spring-beans-2.0.dtd",  
  7.  * no matter whether specified as some local URL that includes "spring-beans"  
  8.  * in the DTD name or as "http://www.springframework.org/dtd/spring-beans-2.0.dtd".  
  9.  *  
  10.  * @author Juergen Hoeller  
  11.  * @author Colin Sampaleanu  
  12.  * @since 04.06.2003  
  13.  * @see ResourceEntityResolver  
  14.  */  

配置dtd從源代碼路徑,不管是否有特殊的本地url包含spring-beans.dtd的名稱 ,實際還是從本地取DTD路徑.[ XML配置還是以網絡地址顯示],這也是爲什麼即使Spring在沒有網絡連接的情況下還是依然可以運行.
那麼這是怎麼查找指定的,請看如下代碼:
Java代碼

public InputSource resolveEntity(String publicId, String systemId)

通過publicId和systemId

比如:

<?xml version="1.0" encoding="UTF-8"?>   <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" " http://www.springframework.org/dtd/spring-beans.dtd ">

其PublicID就是-//SPRING//DTD BEAN//EN.
其 SystemID就是- http://www.springframework.org/dtd/spring-beans.dtd.
在Spring框架中只要你使用標準的xml dtd或者schema聲名,就會自動從spring.jar裏面加載到dtd或schema.其加載程序如下.

  1. Resource resource = new ClassPathResource(dtdFile, getClass());   
  2.                         InputSource source = new InputSource(resource.getInputStream());   
  3.                         source.setPublicId(publicId);   
  4.                         source.setSystemId(systemId);  

這裏的路徑就是相對於此BeansDtdResolver的路徑,也就是org.springframework.beans.factory.xml,所以Spring的dtd等配置文件放在這個目錄下,沒有網絡照樣運行.
接下來讓我們看下Struts是如何加載dtd文件的.

  1. protected String[] registrations =   
  2.        {   
  3.            "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN",   
  4.            "/org/apache/struts/resources/struts-config_1_0.dtd",   
  5.            "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN",   
  6.            "/org/apache/struts/resources/struts-config_1_1.dtd",   
  7.            "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN",   
  8.            "/org/apache/struts/resources/struts-config_1_2.dtd",   
  9.            "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN",   
  10.            "/org/apache/struts/resources/struts-config_1_3.dtd",   
  11.            "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",   
  12.            "/org/apache/struts/resources/web-app_2_3.dtd"  
  13.        };  

publicID直接寫死,systemId直接寫死.哈哈,與Spring對比,Spring的publicId由xml動態指定,如果需要添加dtd或schema版本等不需要修改代碼,Struts必須修改代碼,或許大家也看到差距了,感覺Struts1.X都很久沒更久了,曾經的輝煌都被埋沒了.[不知道哪種利益驅動了,搞了個struts2.x,完全不同的理念]

  1. // Create a new Digester instance with standard capabilities   
  2.         configDigester = new Digester();   
  3.         configDigester.setNamespaceAware(true);   
  4.         configDigester.setValidating(this.isValidating());   
  5.         configDigester.setUseContextClassLoader(true);   
  6.         configDigester.addRuleSet(new ConfigRuleSet());   
  7.   
  8.         for (int i = 0; i < registrations.length; i += 2) {   
  9.             URL url = this.getClass().getResource(registrations[i + 1]);   
  10.   
  11.             if (url != null) {   
  12.                 configDigester.register(registrations[i], url.toString());   
  13.             }   
  14.         }   
  15.   
  16.         this.addRuleSets();  

Struts是使用Digester進行dtd的註冊,現在終於明白了,爲什麼Struts和Spring在沒有網絡的情況下可以運行,但是有的外部包,在沒有網絡的情況下,或者網絡有問題的時候會出問題,這也是我們要注意的,在引入其他項目時,配置文件中的dtd是必須要關注的,在本地開發完全正常,到沒有網絡環境的時候,你就傻眼了.
解決Dtd問題也是我們平時開發必須考慮的.

發佈了6 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章