1. 程式人生 > >mybatis 解析配置檔案(一)之XML的DOM解析方式

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 進行獲取和設定各個屬性, 再次就不過多的進行深入。