使用XSD校驗Mybatis的SqlMapper配置文件(2)

編寫好XSD文件,而後來看怎麼使用XSD文件校驗,並解析SqlMapper文件,也就是實現doParseSqlMapperResourceWithSchema()方法。spring

爲了實現這個功能,有兩個基本要求:apache

(1)兼容性:須要兼容mybatis的原生配置,兼容有兩種層級,一種是使用DTD校驗,這個前面已經說了,走原來的流程,兼容性沒有問題;另外一種就是走XSD校驗,但也須要兼容mybatis原生配置,這種兼容性一方面從上面修改的XSD文件去保證,另外一方面也須要從XML的解析去保證。mybatis

(2)擴展性:修改的目的就是爲了擴展性,因此擴展性也是一個基本要求。可是擴展性不是隨意性,也須要按照規範來擴展,這個規範就是自定義的XSD文件。併發

 

爲了達到這兩個基本要求,下面是個人一種思路,主要借鑑於Spring的自定義命名空間:app

一、建立一個EntityResolver,讀取類路徑下指定模式的配置文件,好比:"classpath*:**/dysd-*-namespaces.ini"ide

二、在ini文件中定義命名空間元信息,如:函數

使用命名空間做爲Section的名稱,下面的schema、parser分別表示命名空間的xsd文件和解析器實現類,這樣就能夠根據XML中的XSD命名空間找到校驗文件,而且有一個解析入口了。spa

說明:code

  1. apache的commons-configuration提供了ini格式文件的讀取API
  2. Spring中使用META-INF/spring.schemas和META-INF/spring.handlers來存儲XSD文件和解析器實現類,這裏我修改成使用ini文件集中配置
  3. 由於讀取的是全部類路徑下知足通配符的ini文件,所以能夠很是簡單的擴展其它命名空間,至於在Java中具體怎麼使用XSD來校驗,這裏就不細說了

我把XML的解析分解爲三要素:解析上下文、解析器、被解析文件。doParseSqlMapperResourceWithSchema()方法也很簡潔:對象

protected void doParseSqlMapperResourceWithSchema(Configuration configuration, Resource mapperLocation){
    ISqlMapperParserContext context = new SqlMapperParserContext(configuration);
    XmlParserUtils.parseXml(context, mapperLocation);
}

解析器接口以下:

public interface IParser<E extends IParserContext> {
    public void parse(E parserContext, String location);
    public void parse(E parserContext, String[] locationPatterns);
    public void parse(E parserContext, InputStream inputStream);
    public void parse(E parserContext, Resource resource);
}

解析上下文和解析器實現類又依次分爲三個層級:

(1)通用解析上下文:

public interface IParserContext { 
    public ProblemReporter getProblemReporter();
    public EventListener getEventListener();
    public SourceExtractor getSourceExtractor();
    public Environment getEnvironment();
}

相應層級的解析器實現類主要負責加載被解析文件(好比將字符串通配符加載爲Resource對象集合),保證不重複解析,保證可併發執行等。

(2)XML解析上下文

public interface IXmlParserContext extends IParserContext{
    public boolean isNamespaceAware();  
    public DocumentLoader getDocumentLoader();
    public EntityResolver getEntityResolver();
    public ErrorHandler getErrorHandler();
    public XmlParserDelegate getDelegate();
}

相應層級的解析器實現類主要負責將Resource轉換爲Document對象,並在轉換的過程當中進行校驗。

(3)SqlMapper解析上下文

public interface ISqlMapperParserContext extends IXmlParserContext{
    public Configuration getConfiguration();
}

相應層級的解析器實現類主要負責查找根元素所在命名空間的解析器,並使用解析器對Document進行解析。

最終,將解析委託給ini配置文件中的SchemaSqlMapperNamespaceParser類,可是由於這個類須要在文本文件中配置,不方便有參數的構造函數,於是進一步委託給SchemaSqlMapperParserDelegate:

public class SchemaSqlMapperNamespaceParser implements INamespaceParser<ISqlMapperParserContext> {

    @Override
    public void init() {
        
    }

    @Override
    public void parse(ISqlMapperParserContext parserContext, Document document, Resource resource) {
        SchemaSqlMapperParserDelegate delegate = new SchemaSqlMapperParserDelegate(parserContext, document, resource);
        delegate.parse();
    }
    
    @Override
    public void destory() {
        
    }
}

至此,XSD校驗已經完成,也已經找到XML解析入口,後續就是在SchemaSqlMapperParserDelegate中真正的解析了。

相關文章
相關標籤/搜索