- 前言
- 第一部分 核心实现
- 第 1 章 Spring 整体架构和环境搭建
- 第 2 章 容器的基本实现
- 第 3 章 默认标签的解析
- 第 4 章 自定义标签的解析
- 第 5 章 bean 的加载
- 第 6 章 容器的功能扩展
- 第 7 章 AOP
- 第二部分 企业应用
- 第 8 章 数据库连接 JDBC
- 第 9 章 整合 MyBatis
- 第 10 章 事务
- 第 11 章 SpringMVC
- 第 12 章 远程服务
- 第 13 章 Spring 消息
2.6.2 验证模式的读取
了解了 DTD 与 XSD 的区别后我们再去分析 Spring 中对于验证模式的提取就更容易理解了。通过之前的分析我们锁定了 Spring 通过 getValidationModeForResource 方法来获取对应资源的的验证模式。
protected int getValidationModeForResource(Resource resource) {
int validationModeToUse = getValidationMode();
//如果手动指定了验证模式则使用指定的验证模式
if (validationModeToUse != VALIDATION_AUTO) {
return validationModeToUse;
}
//如果未指定则使用自动检测
int detectedMode = detectValidationMode(resource);
if (detectedMode != VALIDATION_AUTO) {
return detectedMode;
}
return VALIDATION_XSD;
}
方法的实现其实还是很简单的,无非是如果设定了验证模式则使用设定的验证模式(可以通过对调用 XmlBeanDefinitionReader 中的 setValidationMode 方法进行设定),否则使用自动检测的方式。而自动检测验证模式的功能是在函数 detectValidationMode 方法中实现的,在 detectValidationMode 函数中又将自动检测验证模式的工作委托给了专门处理类 XmlValidationMode Detector,调用了 XmlValidationModeDetector 的 validationModeDetector 方法,具体代码如下:
protected int detectValidationMode(Resource resource) {
if (resource.isOpen()) {
throw new BeanDefinitionStoreException(
"Passed-in Resource [" + resource + "] contains an open stream: " +
"cannot determine validation mode automatically. Either pass in
a Resource " +
"that is able to create fresh streams, or explicitly specify the
validationMode " +
"on your XmlBeanDefinitionReader instance.");
}
InputStream inputStream;
try {
inputStream = resource.getInputStream();
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Unable to determine validation mode for [" + resource + "]: cannot
open InputStream. " +
"Did you attempt to load directly from a SAX InputSource without
specifying the " +
"validationMode on your XmlBeanDefinitionReader instance?", ex);
}
try {
return this.validationModeDetector.detectValidationMode(inputStream);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("Unable to determine validation mode for [" +
resource + "]: an error occurred whilst reading from the
InputStream.", ex);
}
}
XmlValidationModeDetector.java
public int detectValidationMode(InputStream inputStream) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
boolean isDtdValidated = false;
String content;
while ((content = reader.readLine()) != null) {
content = consumeCommentTokens(content);
//如果读取的行是空或者是注释则略过
if (this.inComment || !StringUtils.hasText(content)) {
continue;
}
if (hasDoctype(content)) {
isDtdValidated = true;
break;
}
//读取到<开始符号,验证模式一定会在开始符号之前
if (hasOpeningTag(content)) {
break;
}
}
return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
}
catch (CharConversionException ex) {
// Choked on some character encoding...
// Leave the decision up to the caller.
return VALIDATION_AUTO;
}
finally {
reader.close();
}
}
private boolean hasDoctype(String content) {
return (content.indexOf(DOCTYPE) > -1);
}
只要我们理解了 XSD 与 DTD 的使用方法,理解上面的代码应该不会太难,Spring 用来检测验证模式的办法就是判断是否包含 DOCTYPE,如果包含就是 DTD,否则就是 XSD。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论