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源码深度解析> ...
随机推荐
- 锋利的jQuery第2版学习笔记1~3章
第1章,认识jQuery 注意:使用的jQuery版本为1.7.1 目前流行的JavaScript库 Prototype(http://www.prototypejs.org),成型早,面向对象的思想 ...
- MyBatis(3.2.3) - Configuring MyBatis using XML, typeAliases
In the SQL Mapper configuration file, we need to give the fully qualified name of the JavaBeans for ...
- 用Dalvik指令集写个java类
Dalvik指令集 .class public LCalculate;#定义类名 .super Ljava/lang/Object;#定义父类 .method public static main([ ...
- U大师装系统
主要步骤 1. 若是ghost版本,直接使用智能快速装机版即可安装. 2.安装64位操作系统(iso文件) 1)下载系统地址 http://msdn.itellyou.cn/ . 2)制作好U盘启动, ...
- 实例介绍Cocos2d-x物理引擎:HelloPhysicsWorld
我们通过一个实例介绍一下,在Cocos2d-x 3.x中使用物理引擎的开发过程,熟悉这些API的使用.这个实例的运行后的场景,当场景启动后,玩家可以触摸点击屏幕,每次触摸时候,就会在触摸点生成一个新的 ...
- (转)分布式搜索Elasticsearch——配置
配置文件位于%ES_HOME%/config/elasticsearch.yml文件中,用Editplus打开它,你便可以进行配置. 所有的配置都可以使用环境变量,例如: node.r ...
- 在20上链接db2
首先 db2 connect to CICMDB user ptqs using ptqs; db2进入,出现db2 prep cperftest_bysqlc.sqC bindfile; 就可以sq ...
- JBoss部署项目log4j配置会造成死锁问题,浏览器访问一直pending状态
今天将项目部署到JBoss服务器上,部署成功后,浏览器访问页面一直在等待响应. 查了很长时间,最后在服务器上通过jstack pid命令查看Java堆栈信息,发现了有两个线程死锁. 看到造成死锁的原因 ...
- 利器: 用Siege做Web服务器压测
用「Web压测」关键词检索,能找到好多进行压测的工具,比如ab.Http_load.Webbench.Siege这些,不过今天并不是要对这些工具做对比,毕竟我们只是想得到一个结果.本文主要介绍Sieg ...
- Java.lang.RuntimeException: Unable to instantiate activity ComponentInfo
如果你更新了ADT的新版本,而工程文件中使用了其他的jar包,也可能会出现"java.lang.RuntimeException: Unable to instantiate activit ...