美文网首页
Xmappr源码解析

Xmappr源码解析

作者: 瑜骐 | 来源:发表于2018-05-17 14:20 被阅读0次

    扩展使用说明参见:https://www.jianshu.com/p/772e9b823aab

    1.简介

    Xmappr是一个使用纯Java编写的处理XML的类库,提供一种非常简单的方式来处理XML,可以将任意XML与Java类相映射,具体可以参考https://code.google.com/archive/p/xmappr/

    主要特性:

    • 映射通过注释或外部配置实现
    • 可以缓存未映射元素
    • 保持XML元素顺序
    • 可以自定义类型转换器
    • 完全支持XML命名空间
    • 线程安全(设计用于多线程使用)
    • 不包含任何依赖关系
    • 整个类库大小只有80kb
    • 采用BSD许可

    2.整体类图

    xmapper-类图.jpg

    3.流程

    3.1 整体流程

    Xmappr映射整体分为3大步骤:

    • 解析ConfigRootElement上对应的注解@RootElement,@Attribute和@Element得到对应的ConfigRootElement属性attribute,element等。
    • 解析配置的模板文件,得到ClassConverter中对应的elementMappers和attributeMappers。
    • 根据得到的ClassConverter解析对应的待解析文件设置对应的对象的属性。 整体流程序列图

    3.2 注解解析流程

    xmappr中的注解@RootElement,@Attribute和@Element与对应模板配置文件中节点是对应的,如下面代码:

    @RootElement("root-element")
    public class ConfigRootElement {
        @Attribute
        public String name;
    
        @Attribute(name = "class", converter = ClassNameConverter.class)
        public Class classType;
    
        @Attribute(converter = ClassNameConverter.class, defaultValue = "org.xmappr.converters.ElementConverter")
        public Class<? extends Converter> converter;
    
        @Element
        public List<ConfigNamespace> namespace;
    
        @Element
        public ConfigText text;
    
        @Element
        public List<ConfigAttribute> attribute;
    
        @Element
        public List<ConfigElement> element;
    // 省略对应的方法定义
    }
    public class ConfigAttribute {
        @Attribute
        public String name;
    
        @Attribute
        public String field;
    
        @Attribute
        public String getter;
    
        @Attribute
        public String setter;
    
        @Attribute
        public String defaultvalue;
    
        @Attribute(converter = ClassNameConverter.class, defaultValue = "java.lang.Object")
        public Class targetType;
    
        @Attribute
        public String format;
    
        @Attribute(converter = ClassNameConverter.class, defaultValue = "org.xmappr.converters.ValueConverter")
        public Class<? extends ValueConverter> converter;
    // 省去方法的定义
    }
    
    public class ConfigElement {
       @Attribute
        public String name;
    
        @Attribute
        public String field;
    
        @Attribute
        public String getter;
    
        @Attribute
        public String setter;
    
        @Attribute
        public String defaultvalue;
    
        @Attribute(converter = ClassNameConverter.class, defaultValue = "java.lang.Object")
        public Class targetType;
    
        @Attribute
        public String format;
    
        @Attribute(converter = ClassNameConverter.class, defaultValue = "org.xmappr.converters.ElementConverter")
        public Class<? extends Converter> converter;
    
        @Element
        public List<ConfigNamespace> namespace;
    
        @Element
        public ConfigText text;
    
        @Element
        public List<ConfigAttribute> attribute;
    
        @Element
        public List<ConfigElement> element;
    // 省去方法的定义
    }
    

    对应的配置文件xml如下所示:

    <root-element name="query"
        class="com.ctim.model.domain.evaluate.pengyuan.vehicle.VehicleEvaluateReportInfo">
        <attribute name="treatResult" field="treatResult"
            converter="com.ctim.xmppr.EnumConverter" targetType="com.ctim.model.enums.ThirdPartyQueryResultEnum" format="PENGYUAN" />
        <attribute name="treatErrorCode" field="treatErrorCode"
            converter="com.ctim.xmppr.EnumConverter" targetType="com.ctim.model.enums.ThirdPartyQueryErrorCodeEnum" format="PENGYUAN" />
        <attribute name="errorMessage" field="errorMessage" />
        <attribute name="receiveTime" field="receiveTime" />
        <attribute name="recordId" field="recordId" />
    
        <element name="queryCondition.item" field="otherInfos">
            <element name="name" field="key" />
            <element name="value" field="value" />
        </element>
        <element name="queryResult.item.newCarPrice" field="newCarPrice" />
        <element name="queryResult.item.oldCarPrice" field="oldCarPrice" />
    
    </root-element> 
    

    从上面两段代码可以看出xml文件的根节点“root-element”正好对应的ConfigRootElement对应的注解@RootElement("root-element")的name值,而且root-element节点对应的配置信息正好与ConfigRootElement加上对应注解的对象,如ConfigRootElement对应的属性name加上注解 @Attribute,则在xml配置文件中就有对应的name属性,而且对应的名称完全一致;在比如xml对应的root-element根节点有一个属性class,在ConfigRootElement中就有一个属性如下:

     @Attribute(name = "class", converter = ClassNameConverter.class)
     public Class classType;
    

    虽然对应的名称为classType与root-element对应的属性不一致,但是其是通过@Attribute来实现一致,@Attribute注解对应的name值对应的就是xml配置文件中节点对应的属性值,如果@Attribute对应的name为空,则取对应的属性的名称为xml配置文件中的属性名称。

    从ConfigRootElement对应类中读取注解,并将获得信息放入到ConfigRootElement对应的属性中,具体的流程如下图所示: ConfigurationProcessor.readRootElementAnnotations对应的流程

    3.3 MappingContext.addRootMapper处理流程

    使用方法ConfigurationProcessor.readRootElementAnnotations从ConfigRootElement类中对应的注解读取信息,并将读取到的信息放入到对象ConfigRootElement的属性中,MappingContext.addRootMapper方法主要的作用是通过将ConfigRootElement中的属性解析放入到ClassConverter对象对应的属性中(主要是根据QName映射的map中),具体的流程如下图所示: MappingContext.addRootMapper处理流程

    3.4 RootMapper.getRootObject处理流程

    方法RootMapper.getRootObject(XMLSimpleReader)从对应的xml文件中读取对应的信息,并解析对应的xml文件,对如果输入的是配置文件的话,则会从对应的模板文件中解析得到ConfigRootElement对应的ConfigElement列表,然后在通过MappingContext.addRootMapper方法将ConfigElement中信息放入到ClassConverter中供后续使用;如果处理的是待解析文件,则根据通过配置文件得到的ClassConverter中的信息对待解析文件进行解析,并将解析得到的信息放入到对应的待映射对应的字段中,对应的流程如下所示: RootMapper.getRootObject处理流程

    参考

    xmappr源码地址:https://github.com/lwjaiyjk/xmappr-extend

    相关文章

      网友评论

          本文标题:Xmappr源码解析

          本文链接:https://www.haomeiwen.com/subject/vocbdftx.html