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 的实现方法如下
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
if (systemId != null) {
// 如果是DTD从这里开始
if (systemId.endsWith(DTD_SUFFIX)) {
return this.dtdResolver.resolveEntity(publicId, systemId);
}
// 如果是XSD从这里开始
else if (systemId.endsWith(XSD_SUFFIX)) {
// 通过调用META-INF/Spring.schemas解析
return this.schemaResolver.resolveEntity(publicId, systemId);
}
}
return null;
}
我们可以看到,对不同的验证模式,Spring用了不同的解析器,这里简单描述一下原理,
1.4.1 BeanDtdResolver
比如加载DTD类型的 BeanDtdResolver 的 resolveEntity是直接截取systemId最后的xxx.dtd ,然后去当前路径下寻找,代码如下:
@Override
public InputSource resolveEntity(String publicId, String systemId) throws IOException {
if (logger.isTraceEnabled()) {
logger.trace("Trying to resolve XML entity with public ID [" + publicId +
"] and system ID [" + systemId + "]");
}
//截取systemId最后的xxx.dtd
if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
int lastPathSeparator = systemId.lastIndexOf("/");
for (String DTD_NAME : DTD_NAMES) {
int dtdNameStart = systemId.indexOf(DTD_NAME);
if (dtdNameStart > lastPathSeparator) {
String dtdFile = systemId.substring(dtdNameStart);
if (logger.isTraceEnabled()) {
logger.trace("Trying to locate [" + dtdFile + "] in Spring jar");
}
try {
Resource resource = new ClassPathResource(dtdFile, getClass());
InputSource source = new InputSource(resource.getInputStream());
source.setPublicId(publicId);
source.setSystemId(systemId);
if (logger.isDebugEnabled()) {
logger.debug("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);
}
return source;
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in class path", ex);
}
} }
}
}
1.4.2 PluggableSchemaResolver
而加载XSD类型的PluggableSchemaResolver 类的 resolveEntity 是默认到META-INF/Spring.schemas文件中找到systemid 对应的XSD文件并加载代码如下
@Override
public InputSource resolveEntity(String publicId, String systemId) throws IOException {
if (logger.isTraceEnabled()) {
logger.trace("Trying to resolve XML entity with public id [" + publicId +
"] and system id [" + systemId + "]");
} if (systemId != null) {
//获取 systemId 对应的XSD文件
String resourceLocation = getSchemaMappings().get(systemId);
if (resourceLocation != null) {
Resource resource = new ClassPathResource(resourceLocation, this.classLoader);
try {
InputSource source = new InputSource(resource.getInputStream());
source.setPublicId(publicId);
source.setSystemId(systemId);
if (logger.isDebugEnabled()) {
logger.debug("Found XML schema [" + systemId + "] in classpath: " + resourceLocation);
}
return source;
}
catch (FileNotFoundException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Couldn't find XML schema [" + systemId + "]: " + resource, ex);
}
}
}
}
return null;
}
SAX EntityResolver 的作用的更多相关文章
- sax解析xml,验证格式并支持自定义标签
一.sax简介 SAX是事件驱动型的XML解析方式.顺序读取XML文件,生成事件,传播到用户定义的回调方法中来处理XML文件. 优点: 分段处理xml,而不是将整个xml一次加载进内存,内存占用少,速 ...
- SAX - DefaultHandler
org.xml.sax.helpers.DefaultHandler 实现了 org.xml.sax.EntityResolver.org.xml.sax.DTDHandler.org.xml.sax ...
- XML学习记录1-复习SAX,DOM和JAXB
对xml文档的解析常见的有JDK中的sax,dom,jaxb,stax和JAVA类库JDOM和DOM4J,下面先说说前三个. Java中解析XML的工具很多,像JDOM,DOM4J等,但Java标准库 ...
- XmlBeanFactory的Bean注册
Spring将bean从配置文件到加载到内存中的全过程: BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFac ...
- spring源码深度解析-1核心实现
xml配置文件的读取:1:通过集成字AbstractBeanDefinitionReader中的方法,来使用ResourceLoader将资源文件路径转换为对应的Resource文件2:通过Docum ...
- 【死磕 Spring】----- IOC 之 获取 Document 对象
原文出自:http://cmsblogs.com 在 XmlBeanDefinitionReader.doLoadDocument() 方法中做了两件事情,一是调用 getValidationMode ...
- Spring源码学习笔记1
1.Spring中最核心的两个类 1)DefaultListableBeanFactory XmlBeanFactory继承自DefaultListableBeanFactory,DefaultLis ...
- 【Spring源码分析系列】加载Bean
/** * Create a new XmlBeanFactory with the given input stream, * which must be parsable using DOM. * ...
- spring源码学习之容器的基本实现
最近想拿出一部分时间来学习一下spring的源码,还特意买了一本书结合来看,当然主要是学习并跟着作者的思路来踏上学习spring的源码的道路,特意在此记录一下,<spring源码深度解析> ...
随机推荐
- Spring(3.2.3) - Beans(10): 生命周期
Spring 容器可以管理 singleton 作用域 Bean 的生命周期,容器能够跟踪 Bean 实例的创建.销毁.管理 Bean 生命周期行为主要有两个时机: 注入 Bean 的依赖关系之后 即 ...
- Nginx - Configuration File Syntax
Configuration Directives The Nginx configuration file can be described as a list of directives organ ...
- 【TOMCAT】Tomcat gzip压缩传输数据
概述 由于我们项目的三维模型文件非常大,为了提高传输速度,在服务端对其做zip压缩处理非常有必要,能够极大的提高传输速度. 配置 首先需要修改web.xml中请求的数据文件的mime类型的mappin ...
- 第十二篇、Swift_Sqlite的使用
import UIKit class SQLiteManager: NSObject { private static let manager: SQLiteManager = SQLiteManag ...
- Js中的运算符
运算符 运算符:就是可以运算的符号 比如 + .-.*./ 运算符包括: 算术运算符 比较运算符 逻辑运算符 赋值运算符 字符串运算符 1.算术运算符 +.-.*./.%(求余数).++.-- ++: ...
- 产品经理常用工具Axure、Visio、Mindmanager使用解析(摘)
如果想表现产品的业务流程,那么我建议使用Visio来绘制流程图.如果想表现产品的页面图文布局和页面的跳转关系,我建议使用axure.如果想表现产品的信息架构,我建议使用Mindmanager或Xmin ...
- Poj OpenJudge 百练 2602 Superlong sums
1.Link: http://poj.org/problem?id=2602 http://bailian.openjudge.cn/practice/2602/ 2.Content: Superlo ...
- [转]mysql-5.6.17-win32免安装版配置
1. 下载mysql-5.6.17-win32:官网下载地址百度 2. 解压到自定义目录,我这里演示的是D:\wamp\mysql\ 3. 复制根目录下的my-default.ini,改名为my.in ...
- c#怎么获取当前页面的url
Request.ApplicationPath: /testwebRequest.CurrentExecutionFilePath: /testweb/default.aspxRequest.File ...
- 【ZeroMQ】消息模式
1.请求/应答模式(REP/REQ) 该模式特征: 服务器使用REP类型套接字而客户端使用REQ类型套接字 客户端发送请求和接收答复,而服务器则接收请求并发送答复 客户端可以连接到一个或多个服务器.在 ...