mybatis源碼-解析配置文件(一)之XML的DOM解析方式

@node

簡介

在以前的文章《mybatis 初步使用(IDEA的Maven項目, 超詳細)》中, 講解了mybatis的初步使用, 並總結了如下mybatis的執行流程:git

  1. 經過 Resources 工具類讀取 mybatis-config.xml, 存入 Reader;
  2. SqlSessionFactoryBuilder使用上一步得到的reader建立SqlSessionFactory對象;
  3. 經過 sqlSessionFactory 對象得到SqlSession;
  4. SqlSession對象經過selectList方法找到對應的「selectAll」語句, 執行SQL查詢。
  5. 底層經過 JDBC 查詢後得到ResultSet, 對每一條記錄, 根據resultMap的映射結果映射到Student中, 返回List。
  6. 最後記得關閉 SqlSession

本系列文章深刻講解第 2 步, 解析配置文件。github


Java 中 XML 文件解析

mybatis是基於 XML 來進行配置的, 所以, 咱們首先要知道在Java中, XML是如何解析的。sql

解析方式

XML 常見的解析方式有如下三種: DOMSAXStAX數據庫

1. DOM 方式

DOM 基於樹形結構解析, 它會將整個文檔讀入內存並構建一個 DOM 樹, 基於這棵樹的結構對各個節點進行解析。express

2. SAX 方式

SAX 是基於事件模型的 XML 解析方式, 它不須要將整個 XML 文檔加載到內存中, 而只須要將一部分 XML 文檔的一部分加載到內存中, 便可開始解析。mybatis

3. StAX 方式

StAXSAX 相似, 也是把 XML 文檔做爲一個事件流進行處理, 但不一樣之處在於 StAX 採用的是「拉模式」, 即應用程序經過調用解析器推動解析的過程。dom


DOM 解析 XML

在加載 mybatis-config.xml 配置文件與映射文件時, 使用的是 DOM 解析方式, 並配合使用 XPath 解析 XML 配置文件。ide

XPath 之於 XML 就比如 SQL 之於數據庫。

所謂DOM, 是 Document Object Model 的縮寫, 翻譯過來就是文檔對象模型。

下面咱們就來展現一下該過程。

新建 XML 文件

<CATALOG>
    <CD id="1">
        <TITLE>Empire Burlesque</TITLE>
        <ARTIST>Bob Dylan</ARTIST>
        <COUNTRY>USA</COUNTRY>
        <COMPANY>Columbia</COMPANY>
        <PRICE>10.90</PRICE>
        <YEAR>1985</YEAR>
    </CD>
    <CD id="2">
        <TITLE>Hide your heart</TITLE>
        <ARTIST>Bonnie Tyler</ARTIST>
        <COUNTRY>UK</COUNTRY>
        <COMPANY>CBS Records</COMPANY>
        <PRICE>9.90</PRICE>
        <YEAR>1988</YEAR>
    </CD>
    <CD id="3">
        <TITLE>Greatest Hits</TITLE>
        <ARTIST>Dolly Parton</ARTIST>
        <COUNTRY>USA</COUNTRY>
        <COMPANY>RCA</COMPANY>
        <PRICE>9.90</PRICE>
        <YEAR>1982</YEAR>
    </CD>
    <CD id="4">
        <TITLE>Still got the blues</TITLE>
        <ARTIST>Gary Moore</ARTIST>
        <COUNTRY>UK</COUNTRY>
        <COMPANY>Virgin records</COMPANY>
        <PRICE>10.20</PRICE>
        <YEAR>1990</YEAR>
    </CD>
    <CD id="5">
        <TITLE>Eros</TITLE>
        <ARTIST>Eros Ramazzotti</ARTIST>
        <COUNTRY>EU</COUNTRY>
        <COMPANY>BMG</COMPANY>
        <PRICE>9.90</PRICE>
        <YEAR>1997</YEAR>
    </CD>
</CATALOG>

CATALOG中, 有不少CDCD有着本身的子節點。

DOM 操做相關類

以上的XML, 其對應的樹形結構以下:

文檔結構

而在Java中, 有很節點類型, 如下有幾個主要的接口對應着XML中的各個屬性。

  1. Node : DOM最基本的數據類型。 表示文檔樹中的單個節點
  2. Element:常見的元素節點
  3. Attr:表明元素的屬性
  4. Text:元素或者Att的值(內容)
  5. Document:表明整個XML文檔

Java 讀取 XML 文件

public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException {
    // 獲取 DocumentBuilderFactory 
    DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();

    builderFactory.setValidating(false);
    builderFactory.setNamespaceAware(false);
    builderFactory.setIgnoringComments(true);
    builderFactory.setIgnoringElementContentWhitespace(false);
    builderFactory.setCoalescing(false);
    builderFactory.setExpandEntityReferences(true);

    // 經過 DocumentBuilderFactory 獲取 DocumentBuilder
    DocumentBuilder builder = builderFactory.newDocumentBuilder();

    builder.setErrorHandler(new ErrorHandler() {
        @Override
        public void warning(SAXParseException exception) throws SAXException {
            System.out.println("warning:"+exception.getMessage());
        }

        @Override
        public void error(SAXParseException exception) throws SAXException {
            System.out.println("error:"+exception.getMessage());
        }

        @Override
        public void fatalError(SAXParseException exception) throws SAXException {
            System.out.println("fatalError:"+exception.getMessage());
        }
    });
    
    // 獲得Document文件, 就是XML在JVM中的化身
     InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("xml/cds.xml");
     Document document = builder.parse(is);
    
    // 如下經過 XPath 來獲取對應的信息
    XPathFactory xPathFactory = XPathFactory.newInstance();
    XPath xPath = xPathFactory.newXPath();
    // 解析 //CD//TITLE//text() , 就是獲取全部CD節點下TITLE子節點的文字內容 
    XPathExpression expression = xPath.compile("//CD//TITLE//text()");
    
    Object result = expression.evaluate(document, XPathConstants.NODESET);
    NodeList nodeList = (NodeList)result;
    for (int i = 0; i < nodeList.getLength(); i++) {
        System.out.println(nodeList.item(i).getNodeValue());
    }
}

其主要步驟:

  1. 建立 DocumentBuilderFactory 對象;
  2. 經過 DocumentBuilderFactory 建立DocumentBuilder對象;
  3. 經過DocumentBuilder, 從文件或流中建立經過Document對象;
  4. 建立XPathFactory對象, 並經過XPathFactory建立XPath對象;
  5. 經過XPath解析出XPathExpression對象;
  6. 使用XPathExpression在文檔中搜索出相應的節點。

輸出結果以下:

結果

也能夠調用相應的 API 進行獲取和設置各個屬性, 在此就不過多的進行深刻。

一塊兒學 mybatis

你想不想來學習 mybatis? 學習其使用和源碼呢?那麼, 在博客園關注我吧!!

我本身打算把這個源碼系列更新完畢, 同時會更新相應的註釋。快去 star 吧!!

mybatis最新源碼和註釋

github項目

相關文章
相關標籤/搜索