论坛首页 Java企业应用论坛

Spring,Struts的DTD验证

浏览 2482 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-10-12  
一般比较正式的XML信息中都会包含对应的DTD声明,用来定义 该XML文档中的格式,例如WEB项目中用到的web.xml,例如struts的配置文件struts-config.xml,下面是web.xml中 用到的DTD信息:
<!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文件是存在于互联网的某台主机上的.
[曾经因为ibatis的服务器访问不到,总提示找不到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在没有网络连接的情况下还是依然可以运行.
那么这是怎么查找指定的,请看如下代码:
 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.其加载程序如下.
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文件的.
看Struts源码如下:

 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问题也是我们平时开发必须考虑的.
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics