From 1029363ea14e24827b6c494dfa883a5823b1c09d Mon Sep 17 00:00:00 2001 From: xuchengsheng Date: Sat, 4 Nov 2023 15:33:43 +0800 Subject: [PATCH] =?UTF-8?q?DocumentLoader=E6=BA=90=E7=A0=81=E5=88=86?= =?UTF-8?q?=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-FUTURE.md | 1 + spring-resources/pom.xml | 1 + .../spring-resource-documentLoader/README.md | 227 ++++++++++++++++++ .../spring-resource-documentLoader/pom.xml | 14 ++ .../com/xcs/spring/DocumentLoaderDemo.java | 73 ++++++ .../main/java/com/xcs/spring/bean/MyBean.java | 18 ++ .../src/main/resources/sample.xml | 9 + 7 files changed, 343 insertions(+) create mode 100644 spring-resources/spring-resource-documentLoader/README.md create mode 100644 spring-resources/spring-resource-documentLoader/pom.xml create mode 100644 spring-resources/spring-resource-documentLoader/src/main/java/com/xcs/spring/DocumentLoaderDemo.java create mode 100644 spring-resources/spring-resource-documentLoader/src/main/java/com/xcs/spring/bean/MyBean.java create mode 100644 spring-resources/spring-resource-documentLoader/src/main/resources/sample.xml diff --git a/README-FUTURE.md b/README-FUTURE.md index baf6f5b..721f49a 100644 --- a/README-FUTURE.md +++ b/README-FUTURE.md @@ -64,6 +64,7 @@ - 资源加载与访问 - Resource - ResourceLoader + - DocumentLoader - 元数据 - MetadataReader - AnnotationMetadata diff --git a/spring-resources/pom.xml b/spring-resources/pom.xml index 36b79ec..8c38591 100644 --- a/spring-resources/pom.xml +++ b/spring-resources/pom.xml @@ -15,6 +15,7 @@ spring-resource spring-resource-resourceLoader + spring-resource-documentLoader \ No newline at end of file diff --git a/spring-resources/spring-resource-documentLoader/README.md b/spring-resources/spring-resource-documentLoader/README.md new file mode 100644 index 0000000..8a0ee95 --- /dev/null +++ b/spring-resources/spring-resource-documentLoader/README.md @@ -0,0 +1,227 @@ +## DocumentLoader + +- [DocumentLoader](#documentloader) + - [一、知识储备](#一知识储备) + - [二、基本描述](#二基本描述) + - [三、主要功能](#三主要功能) + - [四、接口源码](#四接口源码) + - [五、主要实现](#五主要实现) + - [六、最佳实践](#六最佳实践) + - [七、与其他组件的关系](#七与其他组件的关系) + - [八、常见问题](#八常见问题) + + +### 一、知识储备 + +1. **XML 解析技术** + + 了解 XML 解析技术,如 DOM(文档对象模型)和 SAX(简单 API for XML)。`DocumentLoader` 通常使用 DOM 来加载和解析 XML 文档,因此理解 DOM 操作是重要的。 +2. **资源加载** + + 了解如何使用 Java 资源加载机制,例如 `ClassLoader` 和 `Resource`,来获取 XML 配置文件。Spring 使用这些机制来加载配置文件。[点击查看Resource接口](https://github.com/xuchengsheng/spring-reading/tree/master/spring-resources/spring-resource),[点击查看ClassLoader接口](https://github.com/xuchengsheng/spring-reading/tree/master/spring-resources/spring-resource-resourceLoader) + +### 二、基本描述 + +`DocumentLoader` 接口是 Spring 框架中的一个核心接口,用于加载和解析 XML 文档,通常用于解析 Spring 配置文件。它定义了一种方法来加载 XML 文档并将其解析为一个 `org.w3c.dom.Document` 对象,以便在 Spring 应用程序中使用,允许开发人员获取和操作 XML 配置文件的内容。这个接口允许配置文件的加载和解析过程在后台自动进行,以支持 Spring 应用的初始化和配置。 + +### 三、主要功能 + +1. **加载 XML 文档**: + + `DocumentLoader` 接口定义了一个方法,用于加载 XML 文档,可以从不同来源(例如文件、资源、URL 等)获取 XML 内容。 +2. **解析 XML 文档** + + 一旦加载了 XML 文档,`DocumentLoader` 将把它解析为一个 `org.w3c.dom.Document` 对象,该对象表示整个 XML 文档的结构,包括元素、属性、文本等。 +3. **支持验证** + + `DocumentLoader` 接口通常可以支持验证,通过指定验证模式(如 DTD 或 XML Schema 验证),可以确保文档的结构和内容符合规定的标准。 +4. **处理实体引用** + + 它还可以处理 XML 文档中的外部实体引用,通过提供 `EntityResolver` 接口来解决外部实体的引用,以确保加载和解析的过程顺利进行。 +5. **错误处理** + + `DocumentLoader` 接口还提供了一个 `ErrorHandler` 接口,用于处理 XML 解析过程中的错误信息,以便及时捕获和处理问题。 + +### 四、接口源码 + +`DocumentLoader` 接口用于加载和解析XML文档的策略,它接受一个`InputSource`,一个实体解析器`EntityResolver`,一个错误处理器`ErrorHandler`,验证模式`validationMode`(可以是DTD或XSD验证),以及一个布尔值`namespaceAware`,表示是否启用XML命名空间支持。方法返回一个加载后的`Document`对象。 + +```java +/** + * 用于加载 XML Document 的策略接口。 + * + * @author Rob Harrop + * @since 2.0 + * @see DefaultDocumentLoader + */ +public interface DocumentLoader { + + /** + * 从提供的 InputSource source 加载一个 Document document。 + * @param inputSource 要加载的文档的来源 + * @param entityResolver 用于解析任何实体的解析器 + * @param errorHandler 用于在加载文档过程中报告任何错误 + * @param validationMode 验证的类型 + * (org.springframework.util.xml.XmlValidationModeDetector#VALIDATION_DTD DTD + * 或 org.springframework.util.xml.XmlValidationModeDetector#VALIDATION_XSD XSD) + * @param namespaceAware 如果需要提供对XML命名空间的支持,则为 true + * @return 加载的 Document document + * @throws Exception 如果发生错误 + */ + Document loadDocument( + InputSource inputSource, EntityResolver entityResolver, + ErrorHandler errorHandler, int validationMode, boolean namespaceAware) + throws Exception; + +} +``` + +### 五、主要实现 + +1. **`DefaultDocumentLoader`** + + `DefaultDocumentLoader` 是 Spring 框架的默认实现,它负责加载和解析XML配置文件,以支持Spring应用程序的初始化和配置。这个实现提供了灵活性,可以根据需要自定义配置文件的加载和解析行为。如果需要使用不同的加载策略或验证模式,可以通过配置来指定不同的`DocumentLoader`实现。 + +~~~mermaid +classDiagram + direction BT + class DocumentLoader { + <> + } + + class DefaultDocumentLoader { + } + + DefaultDocumentLoader --|> DocumentLoader + +~~~ + +### 六、最佳实践 + +使用 Spring 框架的默认文档加载器(`DefaultDocumentLoader`)加载和解析XML配置文件,并以递归方式打印XML文档的详细信息,包括元素名称、属性和文本内容。通过创建一个 `Resource` 对象表示要加载的XML文件,然后使用 `DefaultDocumentLoader` 进行加载和解析,并最后递归打印文档内容。 + +```java +public class DocumentLoaderDemo { + + public static void main(String[] args) { + try { + // 创建要加载的资源对象 + Resource resource = new ClassPathResource("sample.xml"); + + // 创建 DocumentLoader 实例 + DefaultDocumentLoader documentLoader = new DefaultDocumentLoader(); + + // 加载和解析 XML 文档 + Document document = documentLoader.loadDocument(new InputSource(resource.getInputStream()), null, null, 0, true); + + // 打印 XML 文档的内容 + printDetailedDocumentInfo(document); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 打印详细的XML文档信息,包括元素、属性和文本内容。 + * + * @param document 要打印的XML文档对象 + */ + private static void printDetailedDocumentInfo(Document document) { + Element rootElement = document.getDocumentElement(); + printElementInfo(rootElement, ""); + } + + /** + * 递归打印XML元素的详细信息,包括元素名称、属性和子节点。 + * + * @param element 要打印的XML元素 + * @param indent 当前打印的缩进 + */ + private static void printElementInfo(Element element, String indent) { + // 打印元素名称 + System.out.println(indent + "Element: " + element.getNodeName()); + + // 打印元素的属性 + NamedNodeMap attributes = element.getAttributes(); + for (int i = 0; i < attributes.getLength(); i++) { + Node attribute = attributes.item(i); + System.out.println(indent + " Attribute: " + attribute.getNodeName() + " = " + attribute.getNodeValue()); + } + + // 打印元素的子节点(可能是元素或文本) + NodeList childNodes = element.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node childNode = childNodes.item(i); + if (childNode.getNodeType() == Node.ELEMENT_NODE) { + // 如果子节点是元素,递归打印它 + printElementInfo((Element) childNode, indent + " "); + } else if (childNode.getNodeType() == Node.TEXT_NODE) { + // 如果子节点是文本,打印文本内容 + System.out.println(indent + " Text: " + childNode.getNodeValue().trim()); + } + } + } +} +``` + +`MyBean` 的Java类,代表了一个简单的Java Bean。 + +```java +public class MyBean { + + private String message; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} +``` + +`ClassPathResource("sample.xml")` 将加载类路径下名为 "`sample.xml`" 的资源文件的内容。在你的示例配置文件中,这个资源文件定义了一个名为 "`myBean`" 的 Spring Bean,该 Bean 具有一个属性 "message",其值设置为 "Hello World"。 + +```xml + + + + + + + +``` + +运行结果发现,成功的解析出了XML配置文件的结构和内容,包括命名空间、元素、属性和文本内容,以及它们之间的层次关系。 + +```yaml +Element: beans + Attribute: xmlns = http://www.springframework.org/schema/beans + Attribute: xmlns:xsi = http://www.w3.org/2001/XMLSchema-instance + Attribute: xsi:schemaLocation = http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + Text: + Element: bean + Attribute: class = com.xcs.spring.bean.MyBean + Attribute: id = myBean + Text: + Element: property + Attribute: name = message + Attribute: value = Hello World + Text: + Text: +``` + +### 七、与其他组件的关系 + +1. **`XmlBeanDefinitionReader`** + + `XmlBeanDefinitionReader` 是用于读取和解析 XML 配置文件的类,它在 Spring 应用程序上下文的初始化过程中使用 `DefaultDocumentLoader` 来加载和解析配置文件。这是 Spring IOC 容器的关键组件之一,用于注册和管理 Bean 定义。 +2. **`ApplicationContext`** + + 实现Spring 的不同类型的应用程序上下文实现,如 `ClassPathXmlApplicationContext`、`FileSystemXmlApplicationContext`、`XmlWebApplicationContext` 等,都使用 `DefaultDocumentLoader` 或类似的加载器来加载配置文件并创建应用程序上下文。 +3. **Spring Web MVC 配置** + + 在 Spring Web MVC 应用程序中,通常会使用 `DispatcherServlet` 配置中的 `` 元素来指定 Spring 配置文件,这个配置文件将由 `DefaultDocumentLoader` 解析以配置 Web 应用程序上下文。 + +### 八、常见问题 + +1. **XML 文档路径和资源定位问题** + + 确保能够正确找到并加载XML文档,包括检查路径、文件是否存在以及资源定位的正确性。 +2. **XML 验证和格式问题** + + 确保XML文档遵循规范的DTD或XSD,以避免验证失败或格式错误。 +3. **Entity解析问题** + + 提供有效的`EntityResolver`以解析外部实体,避免解析问题。 +4. **错误处理问题** + + 使用`ErrorHandler`来处理解析期间的错误,以便更好地调试和处理问题。 \ No newline at end of file diff --git a/spring-resources/spring-resource-documentLoader/pom.xml b/spring-resources/spring-resource-documentLoader/pom.xml new file mode 100644 index 0000000..2e6f2e8 --- /dev/null +++ b/spring-resources/spring-resource-documentLoader/pom.xml @@ -0,0 +1,14 @@ + + + + spring-resources + com.xcs.spring + 0.0.1-SNAPSHOT + + + 4.0.0 + spring-resource-documentLoader + + \ No newline at end of file diff --git a/spring-resources/spring-resource-documentLoader/src/main/java/com/xcs/spring/DocumentLoaderDemo.java b/spring-resources/spring-resource-documentLoader/src/main/java/com/xcs/spring/DocumentLoaderDemo.java new file mode 100644 index 0000000..75d8e1c --- /dev/null +++ b/spring-resources/spring-resource-documentLoader/src/main/java/com/xcs/spring/DocumentLoaderDemo.java @@ -0,0 +1,73 @@ +package com.xcs.spring; + +import org.springframework.beans.factory.xml.DefaultDocumentLoader; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.w3c.dom.*; +import org.xml.sax.InputSource; + +/** + * @author xcs + * @date 2023年11月04日 14时27分 + **/ +public class DocumentLoaderDemo { + + public static void main(String[] args) { + try { + // 创建要加载的资源对象 + Resource resource = new ClassPathResource("sample.xml"); + + // 创建 DocumentLoader 实例 + DefaultDocumentLoader documentLoader = new DefaultDocumentLoader(); + + // 加载和解析 XML 文档 + Document document = documentLoader.loadDocument(new InputSource(resource.getInputStream()), null, null, 0, true); + + // 打印 XML 文档的内容 + printDetailedDocumentInfo(document); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 打印详细的XML文档信息,包括元素、属性和文本内容。 + * + * @param document 要打印的XML文档对象 + */ + private static void printDetailedDocumentInfo(Document document) { + Element rootElement = document.getDocumentElement(); + printElementInfo(rootElement, ""); + } + + /** + * 递归打印XML元素的详细信息,包括元素名称、属性和子节点。 + * + * @param element 要打印的XML元素 + * @param indent 当前打印的缩进 + */ + private static void printElementInfo(Element element, String indent) { + // 打印元素名称 + System.out.println(indent + "Element: " + element.getNodeName()); + + // 打印元素的属性 + NamedNodeMap attributes = element.getAttributes(); + for (int i = 0; i < attributes.getLength(); i++) { + Node attribute = attributes.item(i); + System.out.println(indent + " Attribute: " + attribute.getNodeName() + " = " + attribute.getNodeValue()); + } + + // 打印元素的子节点(可能是元素或文本) + NodeList childNodes = element.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node childNode = childNodes.item(i); + if (childNode.getNodeType() == Node.ELEMENT_NODE) { + // 如果子节点是元素,递归打印它 + printElementInfo((Element) childNode, indent + " "); + } else if (childNode.getNodeType() == Node.TEXT_NODE) { + // 如果子节点是文本,打印文本内容 + System.out.println(indent + " Text: " + childNode.getNodeValue().trim()); + } + } + } +} diff --git a/spring-resources/spring-resource-documentLoader/src/main/java/com/xcs/spring/bean/MyBean.java b/spring-resources/spring-resource-documentLoader/src/main/java/com/xcs/spring/bean/MyBean.java new file mode 100644 index 0000000..18fe7e1 --- /dev/null +++ b/spring-resources/spring-resource-documentLoader/src/main/java/com/xcs/spring/bean/MyBean.java @@ -0,0 +1,18 @@ +package com.xcs.spring.bean; + +/** + * @author xcs + * @date 2023年11月04日 14时30分 + **/ +public class MyBean { + + private String message; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/spring-resources/spring-resource-documentLoader/src/main/resources/sample.xml b/spring-resources/spring-resource-documentLoader/src/main/resources/sample.xml new file mode 100644 index 0000000..18ebcc4 --- /dev/null +++ b/spring-resources/spring-resource-documentLoader/src/main/resources/sample.xml @@ -0,0 +1,9 @@ + + + + + + +