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


@

簡介

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

  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 步, 解析配置文件。


Java 中 XML 文件解析

mybatis是基於 XML 來進行配置的, 因此, 我們首先要知道在Java中, XML是如何解析的。

解析方式

XML 常見的解析方式有以下三種: DOMSAXStAX

1. DOM 方式

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

2. SAX 方式

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

3. StAX 方式

StAXSAX 類似, 也是把 XML 文檔作為一個事件流進行處理, 但不同之處在於 StAX 采用的是“拉模式”, 即應用程序通過調用解析器推進解析的過程。


DOM 解析 XML

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

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項目


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM