Spring的DTD验证

 

转载:http://a123159521.iteye.com/blog/782198

 

一般比较正式的XML信息中都会包含对应的DTD声明,用来定义 该XML文档中的格式,例如WEB项目中用到的web.xml,例如struts的配置文件struts-config.xml,下面是web.xml中 用到的DTD信息: 

Java代码   收藏代码
  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文件是存在于互联网的某台主机上的. 
[曾经因为ibatis的服务器访问不到,总提示找不到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代码   收藏代码
  1. public InputSource resolveEntity(String publicId, String systemId)  


通过publicId和systemId. 
比如: 

Java代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!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.其加载程序如下. 

Java代码   收藏代码
  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文件的. 
看Struts源码如下: 

Java代码   收藏代码
  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,完全不同的理念] 

Java代码   收藏代码
  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问题也是我们平时开发必须考虑的.

 

=============================分割线=====================================

 

可以将spring配置文件中的

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

 

修改为

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "spring-beans.dtd">

 

spring-beans.dtd文件与spring的配置文件放在同一目录下。

 

你可能感兴趣的:(spring)