我们知道mybatis或者spring都是使用xml文件作为配置文件,配置文件的格式都是定义在叫做.dtd或者.xsd文件中的,当工具在解析用户自己定义的xml文件的时候,如何才能知道用户自定义的文件是否正确的呢?我们不能在xml文件中乱写一些框架不认识的标签,比如在spring的xml文件中写如下<user>标签,毫无疑问会报错。那么框架是怎么来验证我们所写的标签是否正确的呢?

<user>
<id>100</id>
</user>

  由于mybatis使用的是dom解析,利用JDK的dom解析API,如下:

     @Test
public void docFactoryTest() throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setNamespaceAware(false);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(false);
factory.setCoalescing(false);
factory.setExpandEntityReferences(true);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setEntityResolver(new XMLMapperEntityResolver());
      ...(此处省略一部分代码)
Document doc = builder.parse(Resources.getResourceAsStream("mybatis-config.xml"));
System.err.println(doc);

  在第11行中,用到了XMLMapperEntityResolver对象,这个对象定义如下:

 public class XMLMapperEntityResolver implements EntityResolver {

   private static final Map<String, String> doctypeMap = new HashMap<String, String>();

   private static final String IBATIS_CONFIG_PUBLIC = "-//ibatis.apache.org//DTD Config 3.0//EN".toUpperCase(Locale.ENGLISH);
private static final String IBATIS_CONFIG_SYSTEM = "http://ibatis.apache.org/dtd/ibatis-3-config.dtd".toUpperCase(Locale.ENGLISH); private static final String IBATIS_MAPPER_PUBLIC = "-//ibatis.apache.org//DTD Mapper 3.0//EN".toUpperCase(Locale.ENGLISH);
private static final String IBATIS_MAPPER_SYSTEM = "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd".toUpperCase(Locale.ENGLISH); private static final String MYBATIS_CONFIG_PUBLIC = "-//mybatis.org//DTD Config 3.0//EN".toUpperCase(Locale.ENGLISH);
private static final String MYBATIS_CONFIG_SYSTEM = "http://mybatis.org/dtd/mybatis-3-config.dtd".toUpperCase(Locale.ENGLISH); private static final String MYBATIS_MAPPER_PUBLIC = "-//mybatis.org//DTD Mapper 3.0//EN".toUpperCase(Locale.ENGLISH);
private static final String MYBATIS_MAPPER_SYSTEM = "http://mybatis.org/dtd/mybatis-3-mapper.dtd".toUpperCase(Locale.ENGLISH); private static final String MYBATIS_CONFIG_DTD = "org/apache/ibatis/builder/xml/mybatis-3-config.dtd";
private static final String MYBATIS_MAPPER_DTD = "org/apache/ibatis/builder/xml/mybatis-3-mapper.dtd"; static {
doctypeMap.put(IBATIS_CONFIG_SYSTEM, MYBATIS_CONFIG_DTD);
doctypeMap.put(IBATIS_CONFIG_PUBLIC, MYBATIS_CONFIG_DTD); doctypeMap.put(IBATIS_MAPPER_SYSTEM, MYBATIS_MAPPER_DTD);
doctypeMap.put(IBATIS_MAPPER_PUBLIC, MYBATIS_MAPPER_DTD); doctypeMap.put(MYBATIS_CONFIG_SYSTEM, MYBATIS_CONFIG_DTD);
doctypeMap.put(MYBATIS_CONFIG_PUBLIC, MYBATIS_CONFIG_DTD); doctypeMap.put(MYBATIS_MAPPER_SYSTEM, MYBATIS_MAPPER_DTD);
doctypeMap.put(MYBATIS_MAPPER_PUBLIC, MYBATIS_MAPPER_DTD);
} /*
* Converts a public DTD into a local one
*
* @param publicId The public id that is what comes after "PUBLIC"
* @param systemId The system id that is what comes after the public id.
* @return The InputSource for the DTD
*
* @throws org.xml.sax.SAXException If anything goes wrong
*/
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException { if (publicId != null) {
publicId = publicId.toUpperCase(Locale.ENGLISH);
}
if (systemId != null) {
systemId = systemId.toUpperCase(Locale.ENGLISH);
} InputSource source = null;
try {
String path = doctypeMap.get(publicId);
source = getInputSource(path, source);
if (source == null) {
path = doctypeMap.get(systemId);
source = getInputSource(path, source);
}
} catch (Exception e) {
throw new SAXException(e.toString());
}
return source;
} private InputSource getInputSource(String path, InputSource source) {
if (path != null) {
InputStream in;
try {
in = Resources.getResourceAsStream(path);
source = new InputSource(in);
} catch (IOException e) {
// ignore, null is ok
}
}
return source;
} }

  可以看到,当框架在解析xml文件的时候,会把xml文件开头的publicId和systemId传给EntityResolver,而EntityResolver对象就是从classpath中去寻找.dtd文件(文件就在org/apache/ibatis/builder/xml/目录下),在spring中还会存在.xsd文件,原理都是一样的,然后利用classpath中的.dtd文件进行验证。如果不指定这个.dtd文件,那么会从互联网上面下载.dtd文件,性能不好。

mybatis,Spring等工具对xml文件正确性的验证的更多相关文章

  1. mybatis 的 dao 接口跟 xml 文件里面的 sql 是如何建立关系的?一步步解析

    序言 在开始正文之前,首先解释Dao接口和XML文件里的SQL是如何一一对应的? 一句话讲完就是:mybatis 会先解析这些xml 文件,通过 xml 文件里面的命名空间 (namespace)跟d ...

  2. 【报错】spring整合activeMQ,pom.xml文件缺架包,启动报错:Caused by: java.lang.ClassNotFoundException: org.apache.xbean.spring.context.v2.XBeanNamespaceHandler

    spring版本:4.3.13 ActiveMq版本:5.15 ======================================================== spring整合act ...

  3. mybatis 的 dao 接口跟 xml 文件里面的 sql 是如何建立关系的?

    mybatis 会先解析这些xml 文件,通过 xml 文件里面的命名空间 (namespace)跟dao 建立关系:然后 xml 中的每段 sql 会有一个id 跟 dao 中的接口进行关联. 那么 ...

  4. Java 使用poi导入excel,结合xml文件进行数据验证的例子(增加了jar包)

    ava 使用poi导入excel,结合xml文件进行数据验证的例子(增加了jar包) 假设现在要做一个通用的导入方法: 要求: 1.xml的只定义数据库表中的column字段,字段类型,是否非空等条件 ...

  5. Spring介绍及配置(XML文件配置和注解配置)

    本节内容: Spring介绍 Spring搭建 Spring概念 Spring配置讲解 使用注解配置Spring 一.Spring介绍 1. 什么是Spring Spring是一个开源框架,Sprin ...

  6. 【MyBatis学习05】SqlMapConfig.xml文件中的配置总结

    经过上两篇博文的总结,对mybatis中的dao开发方法和流程基本掌握了,这一节主要来总结一下mybatis中的全局配置文件SqlMapConfig.xml在开发中的一些常用配置,首先看一下该全局配置 ...

  7. 【转】Mybatis 3.1中 Mapper XML 文件 的学习详解

    MyBatis 真正的力量是在映射语句中.这里是奇迹发生的地方.对于所有的力量,SQL 映射的 XML 文件是相当的简单.当然如果你将它们和对等功能的 JDBC 代码来比较,你会发现映射文件节省了大约 ...

  8. Spring MVC 配置文件dispatcher-servlet.xml 文件详解

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  9. Spring MVC 配置文件dispatcher-servlet.xml 文件详解(转自 学无止境-yj)

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

随机推荐

  1. java容器collection的一些简单特点

    1.List ArrayList 可随机访问元素,但中间插入和一处元素较慢 LinkedList 在中间进行的插入和删除操作代价较小,随机访问比ArrayList较慢 特性集比ArrayList大 2 ...

  2. ArcGIS Server,rest路径输入要素json 格式描述

    以下内容只测试了简单线, 在ArcGIS Server 的rest路径下可以对服务进行操作,如Query等,这些操作可以输入json 格式要素描述或运行得到即输出json格式要素描述. 如博客:htt ...

  3. .Net深复制、浅复制

    在.Net,大家都知道引用类型的深复制.浅复制吧. ,一般int等值类型是值类型(复制时是直接传值),一般的类(List<T>,Class)是引用类型(复制时传地址),默认是浅复制.若ob ...

  4. Arduino.h

    #ifndef Arduino_h #define Arduino_h #include <stdlib.h> #include <stdbool.h> #include &l ...

  5. 学习laravel遇到的一些错误

    Call to undefined method Illuminate\Foundation\Application::bindShared() 错误代码 Call to undefined meth ...

  6. 移动应用抓包调试利器Charles

    转载:http://www.jianshu.com/p/68684780c1b0 一.Charles是什么? Charles是在 Mac或Windows下常用的http协议网络包截取工具,是一款屌的不 ...

  7. SpringMVC操作指南-MVC-搭建SpringMVC项目结构(基于Java API和注解)

  8. Android Studio: Failed to sync Gradle project 'xxx' Error:Unable to start the daemon process: could not reserve enough space for object heap.

    创建项目的时候报错: Failed to sync Gradle project 'xxx' Error:Unable to start the daemon process: could not r ...

  9. Lua屏蔽对象方法和恢复的方法

    背景 对于OO思想实现的类, 对于某些场景需要屏蔽某些方法, 不让调用.过了这段场景, 就恢复这些类的方法, 可以调用. 例如: 工厂具有开工方法, 但是在晚上不允许开工, 所有在晚上这段时间, 见开 ...

  10. nginx 客户端不缓存header

    location ~* \.(html|htm)$ { add_header Cache-Control no-store; }