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     }
  • 相关阅读:
    BFS visit tree
    Kth Largest Element in an Array 解答
    Merge k Sorted Lists 解答
    Median of Two Sorted Arrays 解答
    Maximal Square 解答
    Best Time to Buy and Sell Stock III 解答
    Best Time to Buy and Sell Stock II 解答
    Best Time to Buy and Sell Stock 解答
    Triangle 解答
    Unique Binary Search Trees II 解答
  • 原文地址:https://www.cnblogs.com/mjorcen/p/3642855.html
Copyright © 2011-2022 走看看