模仿與學習MyBatis - 1.3 xml配置的解析

本文收錄於模仿與學習MyBatis系列


簡述

在前一章《模仿與學習MyBatis - 1.2 DataSource與Session》中實現了一個基本的DataSource與Session。但是DataSource的值需要在Java代碼中設置的,不是很利於更改配置。所以在這一篇,新增一個XMLConfigBuilder類,能讀取xml文件並生成一個DataSource。
最終產生的是一個Java Maven項目,代碼存在github


配置格式

既然要使用xml文件來配置一個DataSource,那麼我們肯定要有一個格式標準,方便XMLConfigBuilder將按此格式讀取xml文件。由於暫時配置內容較少,所以先簡單的定義一下:

<?xml version="1.0" encoding="UTF-8"?>
<database>
    <property name="driverClassName">com.mysql.jdbc.Driver</property>
    <property name="url">jdbc:mysql://localhost:3306/webserver?useUnicode=true&amp;characterEncoding=utf8</property>
    <property name="username">root</property>
    <property name="password">123456</property>
</database>

dom4j

既然xml文件已經有了,我們怎麼解析它呢?我選擇的是dom4j這個包,能讀取每一個結點的標籤、屬性、孩子等,而且使用較爲簡單,只需要輸入流或文件即可解析。如果是普通java項目,需要上網查找dom4j的jar包導入,而如果是maven項目,在pom.xml中加入依賴項即可:

<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>
// 代碼示例
// InputStream in;
SAXReader reader = new SAXReader();
Document document = reader.read(in);
Element root = document.getRootElement();
String tagName = root.getName();    // 標籤名
for (Object item : root.elements("xxx")) {
    // e表示root的標籤名爲xxx的孩子
    Element e = (Element) item;
}

XMLConfigure:獲取配置信息

有了如上知識,已經足以解析一個xml文件了。那麼新建一個config包,在其中加入一個類XMLConfigBuilder,利用dom4j讀取分析及生成DataSource。 以下是讀取過程(一般可以通過以下方式獲取loader,以讀取項目目錄下的文件):

private static ClassLoader loader = ClassLoader.getSystemClassLoader();

public static DataSource build(String resource)
{
    try {
        InputStream stream = loader.getResourceAsStream(resource);
        SAXReader reader = new SAXReader();
        Document document = reader.read(stream);
        Element root = document.getRootElement();
        // Element代入,生成DataSource
        return evalDataSource(root);
    } catch (Exception e) {
        throw new RuntimeException("error occured while evaling xml " + resource);
    }
}

接下來是對內容的解析:

public static DataSource evalDataSource(Element node) throws ClassNotFoundException 
{
    if (!node.getName().equals("database")) {
        throw new RuntimeException("root should be <database>");
    }
    String driverClassName = null;
    String url = null;
    String username = null;
    String password = null;
    for (Object item : node.elements("property")) {
        Element i = (Element) item;         
        String value = getValue(i);
        String name = i.attributeValue("name");
        if (name == null || value == null) 
            throw new RuntimeException("[database]: <property> should contain name and value");

        switch (name) {
            case "url" : url = value; break;
            case "username" : username = value; break;
            case "password" : password = value; break;
            case "driverClassName" : driverClassName = value; break; 
            default : throw new RuntimeException("[database]: <property> unknown name"); 
        }
    }
    return new VDataSource(driverClassName, url, username, password);
}

最後試一段測試代碼:

DataSource ds = XMLConfigBuilder.build("config.xml");
Session session = new VSession(data);
session.exec("select * from article where id<30");

輸出結果如下,與預期一致:

--------------------print--------------------
id=1
title=歡迎來到自由茶社
brief=這裏是大門的入口
content=這裏是大門的入口
father_id=0
author_name=me
create_time=2016-11-16 23:44:36.0
modify_time=2016-12-06 00:41:07.0

id=29
title=第一章
brief=隨便打的內容
content=隨便打的內容
father_id=1
author_name=me
create_time=2016-11-16 23:45:20.0
modify_time=2016-11-16 23:45:20.0

結語

其實可以發現,這裏的XMLConfigBuilder,只是負責讀取DataSource的配置並返回一個設置好值的DataSource。其它需要配置的,如別名、事務等等配置,也是同理的。
下一章,將介紹SessionFactory的意義,以及藉由XMLConfigBuilder實現一個基本的SessionFactory類。

下一篇:模仿與學習MyBatis - 1.4 SessionFactory與Session

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章