zoukankan      html  css  js  c++  java
  • SAX EntityResolver 的作用

    1.1 何为 EntityResolver :

    官方解释: 如果SAX应用程序叙事实现自定义处理外部实体,则必须实现此接口,

    并使用setEntityResolver方法向SAX 驱动器注册一个实例.

    也就是说,对于解析一个xml,sax

    首先会读取该xml文档上的声明,根据声明去寻找相应的dtd定义,以便对文档的进行验证,
    默认的寻找规则,(即:通过网络,实现上就是声明DTD的地址URI地址来下载DTD声明),
    并进行认证,下载的过程是一个漫长的过程,而且当网络不可用时,这里会报错,就是应为相应的dtd没找到,

    1.2 EntityResolver 的作用就是项目本身就可以提供一个如何寻找DtD 的声明方法,

    即:由程序来实现寻找DTD声明的过程,比如我们将DTD放在项目的某处在实现时直接将此文档读取并返回个SAX即可,这样就避免了通过网络来寻找DTD的声明

    1.3 首先看看EntityResolver 接口声明的方法.

      public abstract InputSource resolveEntity (String publicId,
                                                   String systemId)
            throws SAXException, IOException;

    这里,他接收2个参数,publicId ,systemId ,并返回一个InputStream对象,
    这里我们以特定的文件来讲解;

    1.3.1  如果我们在解析验证模式为xsd的配置文件,代码如下 

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    ...
    </beans> 

    读取得到以下参数,

     publicId : null

     systemId : http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

    1.3.2 如果我们解析的是DTD的配置文件;

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

    读取得到以下参数:

    publicId : -//SPRING//DTD BEAN//EN

    systemId : http://www.springframework.org/dtd/spring-beans.dtd

    之前已经提到过,默认的寻找规则,(即:通过网络,实现上就是声明DTD的地址URI地址来下载DTD声明),这样才会造成延迟,用户体验也不好,一般的做法是将验证文件放在自己的工程里面,

    那么怎么做才能将这个Url转换为自己工程里对应的文件呢?我们已加载DTD文件为例看看Spring中是如通过getEntityResolver() 对  EntityResolver 的获取,

    1.4  DelegatingEntityResolver

    我们知道Spring中使用DelegatingEntityResolver 类为 EntityResolver的实现类,

     EntityResolver 的实现方法如下

     1 @Override
     2     public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
     3         if (systemId != null) {
     4             // 如果是DTD从这里开始
     5             if (systemId.endsWith(DTD_SUFFIX)) {
     6                 return this.dtdResolver.resolveEntity(publicId, systemId);
     7             }
     8             // 如果是XSD从这里开始
     9             else if (systemId.endsWith(XSD_SUFFIX)) {
    10                 // 通过调用META-INF/Spring.schemas解析
    11                 return this.schemaResolver.resolveEntity(publicId, systemId);
    12             }
    13         }
    14         return null;
    15     }

    我们可以看到,对不同的验证模式,Spring用了不同的解析器,这里简单描述一下原理,

    1.4.1  BeanDtdResolver 

    比如加载DTD类型的 BeanDtdResolver 的 resolveEntity是直接截取systemId最后的xxx.dtd ,然后去当前路径下寻找,代码如下:

     1 @Override
     2     public InputSource resolveEntity(String publicId, String systemId) throws IOException {
     3         if (logger.isTraceEnabled()) {
     4             logger.trace("Trying to resolve XML entity with public ID [" + publicId +
     5                     "] and system ID [" + systemId + "]");
     6         }
     7         //截取systemId最后的xxx.dtd
     8         if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
     9             int lastPathSeparator = systemId.lastIndexOf("/");
    10             for (String DTD_NAME : DTD_NAMES) {
    11                 int dtdNameStart = systemId.indexOf(DTD_NAME);
    12                 if (dtdNameStart > lastPathSeparator) {
    13                     String dtdFile = systemId.substring(dtdNameStart);
    14                     if (logger.isTraceEnabled()) {
    15                         logger.trace("Trying to locate [" + dtdFile + "] in Spring jar");
    16                     }
    17                     try {
    18                         Resource resource = new ClassPathResource(dtdFile, getClass());
    19                         InputSource source = new InputSource(resource.getInputStream());
    20                         source.setPublicId(publicId);
    21                         source.setSystemId(systemId);
    22                         if (logger.isDebugEnabled()) {
    23                             logger.debug("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);
    24                         }
    25                         return source;
    26                     }
    27                     catch (IOException ex) {
    28                         if (logger.isDebugEnabled()) {
    29                             logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in class path", ex);
    30                         }
    31                     }
    32 
    33                 }
    34             }
    35         }

    1.4.2 PluggableSchemaResolver 

    而加载XSD类型的PluggableSchemaResolver 类的 resolveEntity 是默认到META-INF/Spring.schemas文件中找到systemid 对应的XSD文件并加载代码如下

     1 @Override
     2     public InputSource resolveEntity(String publicId, String systemId) throws IOException {
     3         if (logger.isTraceEnabled()) {
     4             logger.trace("Trying to resolve XML entity with public id [" + publicId +
     5                     "] and system id [" + systemId + "]");
     6         }
     7 
     8         if (systemId != null) {
     9             //获取 systemId 对应的XSD文件
    10             String resourceLocation = getSchemaMappings().get(systemId);
    11             if (resourceLocation != null) {
    12                 Resource resource = new ClassPathResource(resourceLocation, this.classLoader);
    13                 try {
    14                     InputSource source = new InputSource(resource.getInputStream());
    15                     source.setPublicId(publicId);
    16                     source.setSystemId(systemId);
    17                     if (logger.isDebugEnabled()) {
    18                         logger.debug("Found XML schema [" + systemId + "] in classpath: " + resourceLocation);
    19                     }
    20                     return source;
    21                 }
    22                 catch (FileNotFoundException ex) {
    23                     if (logger.isDebugEnabled()) {
    24                         logger.debug("Couldn't find XML schema [" + systemId + "]: " + resource, ex);
    25                     }
    26                 }
    27             }
    28         }
    29         return null;
    30     }
  • 相关阅读:
    SQL Server中事务transaction如果没写在try catch中,就算中间语句报错还是会提交
    EF Core中Key属性相同的实体只能被跟踪(track)一次
    Android--数据持久化之内部存储、Sdcard存储
    SQLite的介绍 操作Sqlite 具体实例
    Android提供了5种方式存储数据:
    Eclipse集成Tomcat的配置步骤实例
    如何实现上下左右键盘控制焦点使之落在相邻文本框或下拉框中-Web开发/JavaScript
    android布局
    android布局 及 布局属性
    Android开发之SD卡上文件操作
  • 原文地址:https://www.cnblogs.com/mjorcen/p/3642855.html
Copyright © 2011-2022 走看看