1 基础支持层
1.1 解析器模块
配置文件xml 解析
1.1.1 常见的xml解析方式
- DOM
基于属性结构的XML解析方式,将整个XML文档读入内存构建一个DOM树,基于树形结构对各节点进行操作
优点:易于编程,可以根据需求在树形结构的各节点之间导航,可以添加修改元素值
缺点:当文件较大时,会造成较大的资源消耗
适用:对XML内容多次随机读取或更改情况
- SAX
基于事件模型的XML解析方式,只需加载一部分到内存中,也不会记录XML中的数据,执行到某节点,会触发注册在该节点上的回调函数,需继承SAX提供的DefaultHandle基类,事件由解析器产生并通过回调函数发送给应该用程序,推模式。
优点: 所占用资源小
缺点:需要开发人员维护多层节点的关系,当文档比较复杂时,维护成本高,另外处理为流式处理,只能单向,没有提供写XML文档的功能,不支持XPath
适用:只扫描一次就能提取到想要数据的情况
- StAX
解析方式与SAX类似,基于事件模型,但采取的是 ”拉模式“,(Pull), 应用程序调用解析器进行解析
优点:简化应用程序处理XML的代码,可以同时处理多个XML文档, 既可以读,也可以写
缺点:不能读取已经读过的内容
适用:只扫描一次就能读取到想要数据的情况
1.1.2 XPath
一句话解析什么是XPath: XPath之于XML就好比SQL之于数据库
XPath 使用示例
public static void main(String[] args) throws Exception {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document doc = documentBuilder.parse("src/com/zz/inventory.xml");
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
XPathExpression expression = xPath.compile("//book[author='Neal Stephenson']/title/text()");
Object evaluate = expression.evaluate(doc, XPathConstants.NODESET);
NodeList nodeList = (NodeList) evaluate;
for (int i = 0; i <nodeList.getLength(); i++) {
System.out.println(nodeList.item(i).getNodeValue());
}
}
1.1.3 XPathParser
XPathParser是 Mybatis 封装了Document, XPath, EntityResolver
- EntityResolver
(The application can also use this interface to redirect system identifiers to local URIs or to look up replacements in a catalog) 应用程序可以使用这个接口来重定向系统标识符通过本地URL或查找目录中的替换项
用来加载本地DTD文件,解析mybatis-config.xml 和 *mapper.xml
- XPathParser 中的createDocument 封装了创建Document对象的方法
private Document createDocument(InputSource inputSource) {
// important: this must only be called AFTER common constructor
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(validation);
factory.setNamespaceAware(false);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(false);
factory.setCoalescing(false);
factory.setExpandEntityReferences(true);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setEntityResolver(entityResolver);
builder.setErrorHandler(new ErrorHandler() {
@Override
public void error(SAXParseException exception) throws SAXException {
throw exception;
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
throw exception;
}
@Override
public void warning(SAXParseException exception) throws SAXException {
}
});
return builder.parse(inputSource);
} catch (Exception e) {
throw new BuilderException("Error creating document instance. Cause: " + e, e);
}
}
解析:示例${username:root}
XPathParser 中提供了一系列eval*() ,其中evalString() 方法,会处理默认值
public String evalString(Object root, String expression) {
String result = (String) evaluate(expression, root, XPathConstants.STRING);
result = PropertyParser.parse(result, variables);
return result;
}
PropertyParser (Property解析器)
public static String parse(String string, Properties variables) {
VariableTokenHandler handler = new VariableTokenHandler(variables);
GenericTokenParser parser = new GenericTokenParser("${", "}", handler);
return parser.parse(string);
}
使用了VariableTokenHandler 和 GenericTokenParser 完成占位符的解析。
GenericTokenParser 不仅用于此处默认值解析,还有用于动态SQL 解析,具体解析行为是由实现了TokenHandler 的类实现。