`

解决java web容器解析xml不能找到DTD问题

    博客分类:
  • XML
阅读更多

项目创建了一个dtd文件,放在tomcat webapp class 目录下面,xml也位于class目录下,xml 的 dtd引用直接为dtd文件名。但是解析时并不是根据xml的相对路径取找dtd文件,而是在执行目录下(也就是tomcat bin目录)下查找,当然找不到。(给xml的dtd引用加上斜杠表示相对路径也没用)
  在网上找了很久,终于有了一个解决方案,与大家共享:

       用DOM解析的时候,我们可以自定义实体的解析器(EntityResolver),而不是使用默认的实体解析器。(默认的解析器会根据实际的url进行读取)
from:http://www.javayou.com/diary/623


般比较正式的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文件是存在于互联网的某台主机上的,因此问题就在于:如果我们的计算机不能保证时时都连在网上,那么怎么老保证解析过程不出错呢?下面我们分别就两种不同的解析方法进行说明。

1. 使用DOM解析

使用DOM解析的时候,我们可以自定义实体的解析器(EntityResolver),而不是使用默认的实体解析器,因为默认的解析器会根据实际的url进行读取,下面是一段如何来解析web.xml的代码:

 

private static void parse(InputStream in) throws Exception{
  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  DocumentBuilder db = dbf.newDocumentBuilder();
  
db.setEntityResolver(new EntityResolver(){
   public InputSource resolveEntity(String publicId, String systemId)
    throws SAXException, IOException{
          for (int i = 0; i < registrations.length; i += 2) {
           if(publicId.equals(registrations[i])){
            String dtd_uri = registrations[i+1];
               InputStream dtd_stream = this.getClass().getResourceAsStream(dtd_uri);
      return new InputSource(dtd_stream);
           }
          }
    return null;
   }});

  Document doc = db.parse(in);
  Element root = doc.getDocumentElement();
  NodeList nodes = root.getElementsByTagName("servlet-mapping");
  int nodec = nodes.getLength();
  for(int i=0;i<nodec;i++){
   Element node = (Element)nodes.item(i);
   Element servlet_name = (Element)node.getElementsByTagName("servlet-name").item(0);
   Element url_pattern = (Element)node.getElementsByTagName("url-pattern").item(0);
   
   String sn = servlet_name.getFirstChild().getNodeValue();
   String up = url_pattern.getFirstChild().getNodeValue();
   System.out.println(sn+"="+up);
  }
 }

private final static String registrations[] = {
        "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN",
        "/web-app_2_2.dtd",
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",
        "/web-app_2_3.dtd"
};

这段代码中把本来从http://java.sun.com/dtd/web-app_2_3.dtd地址中读取dtd的信息改为了从当前类路径中读取,也就是/web-app_2_3.dtd,通过重新定义InputSource来返回/web- app_2_3.dtd数据流,从而让XML解析器不从网上获取DTD信息。当然,这样做的前提是事先必须把dtd文件保存在类路径所在的目录中,以便自定义的EntityResolver可以读取到。

2. 使用Digester解析

使用Digester解析时原理也是一样的,代码有所不同而已:

 

Digester digester = new Digester();
digester.push(this);
digester.setNamespaceAware(true);
digester.setValidating(false);

// Register our local copy of the DTDs that we can find
for (int i = 0; i < registrations.length; i += 2) {
    URL url = this.getClass().getResource(registrations[i+1]);
    if (url != null)
        digester.register(registrations[i], url.toString());            
}

其中registrations与前一段代码相同。

通过上面两种处理办法以后,XML的解析器就不再从网上获取dtd文件,这也是为什么Tomcat包括struts项目可以在计算机没有联网下工作的原因,因为Tomcat需要解析web.xml,struts需要解析web.xml以及struts-config.xml,而这两个文件的dtd恰恰都是通过一个url给出的。

需要说明一点的是,这样做的目的并不是说屏蔽了DTD的作用,毕竟DTD是用来验证XML语法的,如果去掉了,验证的功能就没有了,因此DTD不能去掉。这样做的真正目的是在保留DTD功能外使应用程序在无网络连接的情况下也可以运行。

分享到:
评论

相关推荐

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part2

    此外,本书的配套光盘还免费提供了价值人民币330元的java教学视频,对java语言进行了全面讲解,帮助一些不会java语言的读者快速地从java基础知识的学习中过渡到java web的学习与开发上. 第1部分 xml篇. 第1章 xml...

    java web web.xml

    在Java Web开发中,`web.xml`扮演着至关重要的角色,它是Web应用程序的核心配置文件,用于定义和管理Servlet、过滤器、监听器等组件的行为,以及处理URL映射、会话管理和上下文参数等关键设置。下面将深入解析`web....

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part3

    此外,本书的配套光盘还免费提供了价值人民币330元的java教学视频,对java语言进行了全面讲解,帮助一些不会java语言的读者快速地从java基础知识的学习中过渡到java web的学习与开发上. 第1部分 xml篇. 第1章 xml...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part4

    此外,本书的配套光盘还免费提供了价值人民币330元的java教学视频,对java语言进行了全面讲解,帮助一些不会java语言的读者快速地从java基础知识的学习中过渡到java web的学习与开发上. 第1部分 xml篇. 第1章 xml...

    java后端开发dtd文件

    这些DTD文件定义了XML配置文件的合法元素、属性及其关系,帮助开发者编写正确的配置,同时在解析XML时进行验证,确保符合规范。 使用DTD可以提升代码质量和一致性,降低因配置错误导致的问题。在实际项目中,开发者...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part5

    此外,本书的配套光盘还免费提供了价值人民币330元的java教学视频,对java语言进行了全面讲解,帮助一些不会java语言的读者快速地从java基础知识的学习中过渡到java web的学习与开发上. 第1部分 xml篇. 第1章 xml...

    web.xml+详细解析四合一

    了解和掌握web.xml的详细结构和使用,对开发者来说是一项重要的基础技能,它有助于正确地部署和运行Web应用,同时也能够帮助开发者在遇到问题时,能够快速定位和解决问题。随着技术的发展,虽然现代的Java EE应用...

    web.xml配置详解

    web.xml 文件必须遵守 DTD 文件的规则,否则将无法被正确解析。 部署描述符 web.xml 文件是 Servlet/JSP 应用的部署描述符,用于描述应用程序的各个方面的元素,如 servlet 注册、servlet 映射以及监听器注册。...

    DTD约束文档

    7. **DTD在Servlet配置中的应用**:讲解如何根据Servlet 2.3 DTD来正确配置`web.xml`,确保Servlet容器能够正确解析和处理Web应用的配置。 8. **错误处理和验证**:当XML文档不遵循DTD约束时,解析器会报告错误,...

    DTD文件和XSD文件

    在给定的压缩包文件中,我们看到的是与Java Web开发框架Struts 2和Servlet容器相关的DTD和XSD文件。 首先,让我们了解DTD和XSD的基本概念: 1. DTD(Document Type Definition):DTD是一种早期的XML文档结构定义...

    web.xml.txt

    根据提供的文件信息,我们可以深入探讨以下几个关键的知识...通过上述详细的解析,我们可以了解到 `web.xml` 文件在 Java Web 开发中的重要作用及其配置细节。这些知识点对于理解和掌握 Java Web 开发具有重要的意义。

    2022年Java中关于XML的APIJava教程.docx

    JAXP提供了一组通用接口,用于在Java中解析XML文档,包括DOM、SAX和XSLT。它允许程序员在不修改代码的情况下更换具体的实现,如解析器或XSLT处理器。JAXP1.0支持XML1.0、XML Namespace1.0、SAX1.0和DOM Level 1,而...

    部署描述文件web.xml配置详解.doc

    本文将深入解析`web.xml`的各项元素及其作用,帮助开发者更好地理解并利用这一配置文件。 #### 二、`web.xml`的基本结构 `web.xml`文件以XML格式编写,主要包括以下几个部分: 1. **XML声明**:指定了XML文档的...

    Java中关于XML的API

    JAXP 是一个用于解析XML文档的Java API集合,它提供了一种统一的方式来访问不同的XML解析器。通过JAXP,开发人员可以在应用程序中使用通用的接口,当需要更换解析器时无需更改代码。JAXP的主要功能包括DOM解析、SAX...

    web.xml元素详解

    在Java Web开发中,`web.xml`是部署描述符的核心组成部分,它定义了Web应用程序的配置信息。此文件位于WEB-INF目录下,被服务器用来解析Web应用的各种设置,如Servlet映射、过滤器配置、监听器注册等。下面将对`web....

    SSM高级框架所需dtd

    这里,DTD保证了`web-app`元素及其子元素的正确性,使得Servlet容器能够解析并加载配置。 在MyBatis中,虽然XML映射文件的定义不直接使用DTD,但MyBatis有自己的Schema用于验证XML配置。例如: ```xml &lt;?xml ...

    《动态Web数据库技术——基于JSP和XML技术实现》-王红-源代码-3314

    7. Web应用部署与调试:书中可能涵盖了如何在Web容器(如Tomcat)中部署JSP应用,以及如何使用日志和调试工具来定位和解决问题。 8. 安全性与优化:这可能涉及到输入验证、防止SQL注入、 session管理以及性能优化等...

Global site tag (gtag.js) - Google Analytics