mybatis配置阶段—— xml解析工具

概述

接下来我们进入mybatis的初始化配置阶段。

配置阶段就是读取mybatis的配置文件及我们编写的XML文件。

在讲解mybatis的初始化配置之前,我们先了解初始化配置阶段要用到的基础支撑组件。

这一篇讲解的是xml文件解析器组件

DOM

java编程中我们常见的XML解析方式有三种:

- DOM解析方式:加载整个XML到内存构建DOM树,数据量较大时,较消耗内存

- SAX解析方式:基于事件模型的XML解析方式,流式处理方式,处理XML文档只能向后单项进行,没法自由导航,且需要开发人员自己维护节点关系,面对复杂的XML程序会比较复杂。

StAX解析方式:同时支持DOM和SAX解析方式。

上面仅对java中常见的XML解析几种方式做简要介绍,大致了解即可。

mybatis采用的是DOM解析方式,并结合了XPath工具。

XPath之于XML类似于Sql之于数据库。就是XML的一个查询工具。

通过一段简单代码了解DOM和XPath

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yanlink.mapper.SysUserMapper">

    <resultMap id="sysUserMap" type="com.yanlink.entity.SysUser">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="sex" column="sex"/>
        <result property="password" column="password"/>
    </resultMap>

    <select id="getUser" resultType="SysUser">
        select id,name,password,sex from sys_user where id=#{id}
    </select>
</mapper>

上面是一个我们经常编写的操作数据库的xml文件

下面我通过xpath来读取这个xml文件

public class XPathDemo {
    public static void main(String[] args) {
        try {
            InputStream inputStream = XPathDemo.class.getResourceAsStream("/mapper/SysUserMapper.xml");

            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document document = db.parse(inputStream);

            XPath xPath =  XPathFactory.newInstance().newXPath();
            Node mapper = (Node) xPath.evaluate("/mapper", document, XPathConstants.NODE);
            System.out.println(mapper.getNodeName()+" "+mapper.getAttributes().getNamedItem("namespace"));
            // 输出mapper namespace="com.yanlink.mapper.SysUserMapper"

            Node resultMap = (Node) xPath.evaluate("resultMap", mapper, XPathConstants.NODE);
            System.out.println(resultMap.getNodeName()+" "+resultMap.getAttributes().getNamedItem("id")+" "+resultMap.getAttributes().getNamedItem("type"));
            // 输出:resultMap id="sysUserMap" type="com.yanlink.entity.SysUser"

            NodeList results = (NodeList) xPath.evaluate("result", resultMap, XPathConstants.NODESET);
            for (int i = 0; i < results.getLength(); i++) {
                Node result = results.item(i);
                NamedNodeMap nodeMap = result.getAttributes();
                System.out.println(result.getNodeName()+" "+nodeMap.getNamedItem("property")+" "+nodeMap.getNamedItem("column"));
            }
            // 输出: result property="name" column="name"
            //result property="sex" column="sex"
            //result property="password" column="password"

            /**
             * 我们还可以直接定位到对应的node
             */
            Node select = (Node) xPath.evaluate("//select[@id='getUser']", document, XPathConstants.NODE);
            NamedNodeMap selectNameNodeMap = select.getAttributes();
            System.out.println(select.getNodeName()+" "+ selectNameNodeMap.getNamedItem("id") +" "+selectNameNodeMap.getNamedItem("resultType"));
            // 输出:select id="getUser" resultType="SysUser"

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

相信通过上面一段代码,我们大致可能了解XPath是做什么的了。

这里并不是要大家来深入了解XPath,如果对这个确实感兴趣,可以去查阅相关的资料,我们这里的目的还是介绍下XPath的概念,便于我们引入myabtis的xml解析工具XPathParser

XPathParser

XPathParser其实就是对XPath操作XML文档的封装。

看下XPathParser的属性

 private final Document document;
  private XPath xpath;

其实也就两个东西,一个document,一个xpath,document是文档,xpath读取文档信息

再看看其使用率比较高的方法


public List<XNode> evalNodes(Object root, String expression) {
    List<XNode> xnodes = new ArrayList<XNode>();
    NodeList nodes = (NodeList) evaluate(expression, root, XPathConstants.NODESET);
    for (int i = 0; i < nodes.getLength(); i++) {
      xnodes.add(new XNode(this, nodes.item(i), variables));
    }
    return xnodes;
  }

public XNode evalNode(Object root, String expression) {
    Node node = (Node) evaluate(expression, root, XPathConstants.NODE);
    if (node == null) {
      return null;
    }
    return new XNode(this, node, variables);
  }

  private Object evaluate(String expression, Object root, QName returnType) {
    try {
      return xpath.evaluate(expression, root, returnType);
    } catch (Exception e) {
      throw new RuntimeException("Error evaluating XPath.  Cause: " + e, e);
    }
  }
 

注意这里返回的不再是Node对象,而是MyBatis封装的XNode对象了

public class XNode {

  private final Node node;
  private final String name;
  private final String body;
  private final Properties attributes;
  private final Properties variables;
  private final XPathParser xpathParser;

  private Properties parseAttributes(Node n) {
    Properties attributes = new Properties();
    NamedNodeMap attributeNodes = n.getAttributes();
    if (attributeNodes != null) {
      for (int i = 0; i < attributeNodes.getLength(); i++) {
        Node attribute = attributeNodes.item(i);
        String value = PropertyParser.parse(attribute.getNodeValue(), variables);
        attributes.put(attribute.getNodeName(), value);
      }
    }
    return attributes;
  }
}

XNode也就是对Node进行了一次封装,让我们更好地操作Node的属性,及获取其内容

如果对我实现的简化的XPathParser感兴趣可以下载下面的项目

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值