四、获取验证模型

获取验证模型

接《加载BeanDefinition》文。

getValidationModeForResource

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//禁用验证模式,值为0
public static final int VALIDATION_NONE = XmlValidationModeDetector.VALIDATION_NONE;
//自动获取验证模式,值为1
public static final int VALIDATION_AUTO = XmlValidationModeDetector.VALIDATION_AUTO;
//DTD 验证模式,值为2
public static final int VALIDATION_DTD = XmlValidationModeDetector.VALIDATION_DTD;
//XSD 验证模式,值为3
public static final int VALIDATION_XSD = XmlValidationModeDetector.VALIDATION_XSD;
//验证模式。默认为自动模式。
private int validationMode = VALIDATION_AUTO;

protected int getValidationModeForResource(Resource resource) {
// <1> 获取指定的验证模式
int validationModeToUse = getValidationMode();
// 如果手动指定,则直接返回
if (validationModeToUse != VALIDATION_AUTO) {
return validationModeToUse;
}
// 自动获取验证模式
int detectedMode = detectValidationMode(resource);
if (detectedMode != VALIDATION_AUTO) {
return detectedMode;
}
// 否则,使用 VALIDATION_XSD
return VALIDATION_XSD;
}
  • <1> 处,调用 getValidationMode() 方法,获取指定的验证模式( validationMode )。如果有手动指定,则直接返回。
1
2
3
4
5
6
7
8
public void setValidationMode(int validationMode) {
this.validationMode = validationMode;
}

public int getValidationMode()
//如上段,该值默认为VALIDATION_AUTO
return this.validationMode;
}
  • <2> 处,调用 detectValidationMode(Resource resource) 方法,自动获取验证模式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//下段介绍XmlValidationModeDetector
private final XmlValidationModeDetector validationModeDetector = new XmlValidationModeDetector();

//检测对{@link Resource}标识的XML文件执行哪种验证。如果文件具有{@code DOCTYPE}定义,则使用DTD验证,否则采用XSD验证。在接下来的方法中可以看到。
protected int detectValidationMode(Resource resource) {
// 不可读,抛出 BeanDefinitionStoreException 异常
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);
}

// <x> 获取相应的验证模式
try {
//XmlValidationModeDetector上边已经定义
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

org.springframework.util.xml.XmlValidationModeDetector ,XML 验证模式探测器。

主要看上段return this.validationModeDetector.detectValidationMode(inputStream);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public int detectValidationMode(InputStream inputStream) throws IOException {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
// 是否为 DTD 校验模式。默认为,非 DTD 模式,即 XSD 模式
boolean isDtdValidated = false;
String content;
// <0> 循环,逐行读取 XML 文件的内容
while ((content = reader.readLine()) != null) {
content = consumeCommentTokens(content);
// 如果是注释,或者没内容,跳过
if (this.inComment || !StringUtils.hasText(content)) {
continue;
}
// <1> 包含 DOCTYPE 为 DTD 模式
//如下
if (hasDoctype(content)) {
isDtdValidated = true;
break;
}
// <2>hasOpeningTag方法会校验,如果这一行有<,并且<后面跟着的是字母,则返回 true 。
//如下
if (hasOpeningTag(content)) {
break;
}
}
return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
}
//如果发生 CharConversionException 异常,则为 VALIDATION_AUTO 模式。
catch (CharConversionException ex) {
return VALIDATION_AUTO;
}
}

private static final String DOCTYPE = "DOCTYPE";
private boolean hasDoctype(String content) {
return content.contains(DOCTYPE);
}

private boolean hasOpeningTag(String content) {
if (this.inComment) {
return false;
}
int openTagIndex = content.indexOf('<');
return (openTagIndex > -1 && (content.length() > openTagIndex + 1) &&
Character.isLetter(content.charAt(openTagIndex + 1)));
}

四、获取验证模型
http://www.muzili.ren/2022/06/11/获取验证模型/
作者
jievhaha
发布于
2022年6月11日
许可协议