【仅供内部供应商使用,不提供对外解答和培训】

Page tree

【仅供内部供应商使用,不提供对外解答和培训】

Skip to end of metadata
Go to start of metadata

1.配置文件前世:

配置文件都继承自XMLFileManager,需要提供readXml和writeXml方法的实现,其中每个xml读写都有深深的硬编码的烙印,这就导致了不同xml文件的读写实现都紧紧与内部数据结构耦合,因此每个xmlFileManager的读写实现都有很强的个性,导致难以从外部进行读写抽象。

在xml文件的实现类中,包含了很多成员变量,有一些基本类型(直接写标签),有一些XmLable的实现(也实现了readXml和writeXml方法,当读写这些变量时,委托他们各自的实现来进行读写),还有一些普通对象(这些对象没有实现readXml和writeXml,只是记录了一下对象里面的信息,读取的时候根据这些信息重新构造对象)

比如ConfigManager中,有成员变量(基本类型) private String resServerPath,直接在xml里面定义一个标签,然后把值写进去,有成员变量(实现了Xmlable接口)private EmbeddedTableData embeddedTableData,读写的时候直接调用embeddedTableData.readXml和writeXml,还有成员变量(普通对象)private Map styleMap = new ListMap(); key为String,value为Style,其中Style就是样式,写入的时候直接暴力记录Style里面信息,读取的时候根据这些信息重新构建Style。因为对象的读写没有一些强制的约束,所以基本上不可能从外部抽象文件读写。

2.配置文件今生

基于以上原因,只能侵入配置文件内部,来逐层代理各个成员变量(这里面用ConfigHolder来进行封装,所有的读写逻辑根据代理对象的类型,由ConfigHolder来处理),这样至少可以保证配置文件类对外提供的接口不变。API提供了几个生成holder的工厂类,来生成各种holder。工厂类如下

(修改了工厂接口,不需要写property和nameSpace,property默认时成员变量的变量名,如果想自定义property,则在相应的成员变量上加注解Identifier)

package com.fr.config.holder.factory;

import com.fr.config.holder.Conf;
import com.fr.config.holder.impl.ColConf;
import com.fr.config.holder.impl.MapConf;
import com.fr.config.holder.impl.ObjConf;
import com.fr.config.holder.impl.ObjectColConf;
import com.fr.config.holder.impl.ObjectMapConf;
import com.fr.config.holder.impl.SimConf;

import java.util.Collection;
import java.util.Map;

/**
 * 包装类工厂
 * http://www.finedevelop.com/pages/viewpage.action?pageId=18648778
 */
public class Holders {
    /**
     * 创建一个基本类型的Holder类,只要T对象中没有成员变量ConfigHolder,就要用这个包装器
     *
     * @param property  属性标签
     * @param t         默认值
     * @param nameSpace 名字空间
     * @param <T>       包装的值类型
     * @return 属性节点的包装
     * @see Holders#simple(Object)
     */
    @Deprecated
    public static <T> Conf<T> simple(String property, T t, String nameSpace) {
        return new SimConf<T>(property, t).setNameSpace(nameSpace);
    }

    public static <T> Conf<T> simple(T t) {
        return new SimConf<T>(t);
    }

    /**
     * 创建一个类型为T的对象的Holder,这个对象T里面会有ConfigHolder成员变量
     *
     * @param property  属性标签
     * @param t
     * @param type
     * @param nameSpace 名字空间
     * @param <T>
     * @return 属性节点的包装
     * @see Holders#obj(Object, Class)
     */
    @Deprecated
    public static <T> Conf<T> obj(String property, T t, Class<T> type, String nameSpace) {
        return new ObjConf<T>(property, t, type).setNameSpace(nameSpace);
    }

    public static <T> Conf<T> obj(T t, Class<T> type) {
        return new ObjConf<T>(t, type);
    }


    /**
     * 创建一个类型K(基本类型)的Collection的Holder,只要对象中没有成员变量ConfigHolder,就要用这个包装器
     *
     * @param property   属性标签
     * @param collection
     * @param valueType
     * @param nameSpace  名字空间
     * @param <K>
     * @return 属性节点的包装
     * @see Holders#objCollection(Collection, Class)
     */
    @Deprecated
    @SuppressWarnings("unchecked")
    public static <K> Conf<Collection<K>> collection(String property, Collection<K> collection, Class<K> valueType, String nameSpace) {
        return new ColConf(property, collection, valueType).setNameSpace(nameSpace);
    }

    @SuppressWarnings("unchecked")
    public static <K> ColConf<Collection<K>> collection(Collection<K> collection, Class<K> valueType) {
        return new ColConf(collection, valueType);
    }

    /**
     * 创建一个类型T的Collection的Holder,这个对象T里面会有ConfigHolder成员变量
     *
     * @param property   属性标签
     * @param collection
     * @param type
     * @param nameSpace  名字空间
     * @param <T>
     * @return 属性节点的包装
     * @see Holders#collection(Collection, Class)
     */
    @Deprecated
    public static <T> ObjectColConf<Collection<T>> objCollection(String property, Collection<T> collection, Class<T> type, String nameSpace) {
        return new ObjectColConf<Collection<T>>(property, collection, type).setNameSpace(nameSpace);
    }

    public static <T> ObjectColConf<Collection<T>> objCollection(Collection<T> collection, Class<T> type) {
        return new ObjectColConf<Collection<T>>(collection, type);
    }

    public static <T> ObjectColConf<Collection<T>> objCollection(Collection<T> collection, Class<T> type, boolean order) {
        return new ObjectColConf<Collection<T>>(collection, type, order);
    }

    /**
     * 创建一个key和value均为基本类型的Map的Holder。只要K,V对象中没有成员变量ConfigHolder,就要用这个包装器,keyType和valueType均不能为空
     *
     * @param property  属性标签
     * @param map
     * @param keyType
     * @param valueType
     * @param nameSpace 名字空间
     * @param <K>       包装的键值对中键类型
     * @param <V>       包装的键值对中值类型
     * @return 属性节点的包装
     * @see Holders#map(Map, Class, Class)
     */
    @Deprecated
    @SuppressWarnings("unchecked")
    public static <K, V> MapConf<Map<K, V>> map(String property, Map<K, V> map, Class<K> keyType, Class<V> valueType, String nameSpace) {
        return new MapConf(property, map, keyType, valueType).setNameSpace(nameSpace);
    }

    @SuppressWarnings("unchecked")
    public static <K, V> MapConf<Map<K, V>> map(Map<K, V> map, Class<K> keyType, Class<V> valueType) {
        return new MapConf(map, keyType, valueType);
    }

    /**
     * value是V类型的Map的Holder,这个对象V里面会有ConfigHolder成员变量
     * K只能是基本类型或者字符串类型,又或者 K是一些简单的类型,这个不同的K对象可以转换成不同的String,注册K类型的ValueWriter对象,用来将K对象转换成String
     * 同样 也要注册K类型的ValueReader,用来从String中恢复重新构造K对象,ValueReader.registerReader,  ValueWriter.registerWriter
     * keyType可以为空,但是map中的key只能是基本类型和String,ValueType可以为空,但是只能是复合类型。
     *
     * @param property  属性标签
     * @param map
     * @param keyType
     * @param valueType
     * @param nameSpace 名字空间
     * @param <K>
     * @param <V>
     * @return 属性节点的包装
     * @see Holders#objMap(Map, Class, Class)
     */
    @Deprecated
    public static <K, V> ObjectMapConf<Map<K, V>> objMap(String property, Map<K, V> map, Class<K> keyType, Class<V> valueType, String nameSpace) {
        return new ObjectMapConf<Map<K, V>>(property, map, keyType, valueType).setNameSpace(nameSpace);
    }

    public static <K, V> ObjectMapConf<Map<K, V>> objMap(Map<K, V> map, Class<K> keyType, Class<V> valueType) {
        return new ObjectMapConf<Map<K, V>>(map, keyType, valueType);
    }

    public static <K, V> ObjectMapConf<Map<K, V>> objMap(Map<K, V> map, Class<K> keyType, Class<V> valueType, boolean ordered) {
        return new ObjectMapConf<Map<K, V>>(map, keyType, valueType, ordered);
    }
}



使用规则:配置类对象中的成员变量

1.如果成员变量是基本类型,String或者JDK的内置类型(不包括集合),则使用 Conf<T> xxx = Holders.simple(t));

2.如果成员变量是Map类型,而且Map的key和value类型都是是基本类型,String类型或者JDK的内置类型(不包括集合),则使用 MapConf<K,V> xx = Holdes.map(map,keyType,valueType); keyType和ValueType需要明确指定,另外MapConf提供了一些操作map的方法,比如get,put,remove和clear。如果有个配置文件A,其中有个成员变量B是这种类型,假如需要修改Map,则需要在A中提供修改B的方法,调用MapConf修改。外部修改B,严禁使用 A.getB.put方法,remove等方法,这样只会修改内存,不会进行持久化存储。

3.如果成员变量是集合类型,而且集合中的类型是基本类型,String或者JDK的内置类型,则使用ColConf<Collection<K>> xxxx = Holders.collection(collection,valueType);

4.如果成员变量是我们报表的业务对象,那么这个成员变量需要用Conf<T> tt = Holders.obj(t,type),同样的成员变量所在类中的成员变量也需要根据其类型用 Conf来进行包装,。

5.如果成员变量是集合类型,值为报表的业务对象,那么需要 用ObjectColConf<T> ttt = Holders.objCollection();,这个ObjectColConf提供了集合操作的 add,remove,clear方法,如果修改Collection中,需要在配置类中提供修改集合的方法,委托ObjectColConf来进行修改。

6.如果成员变量是Map类型,key为基本类型,String或者JDK的内置类型(不包括集合),value是报表的业务对象,那么要使用MapConf<Map<K.V>> kkk = Holders.map(map,keytype,valueType); keytype和valueType可以为空。

注意,如果是报表的业务对象,均需要继承UniqueKey.

这边有使用范例:2-配置工厂使用指南

还有对一些复杂xmlable的包装类,(为啥还有提供呢,因为这些对象的结构复杂,涉及的类众多,会导致代理holder类层次过多,也会污染原来的业务对象,影响性能。直接包装Xmlable,委托其自身的readXml和writeXml来进行读写)

非常不推荐使用

package com.fr.config.holder.factory;


import com.fr.config.holder.Conf;
import com.fr.config.holder.impl.xml.XmlColConf;
import com.fr.config.holder.impl.xml.XmlConf;
import com.fr.config.holder.impl.xml.XmlMapConf;
import com.fr.stable.xml.XMLable;

import java.util.Collection;
import java.util.Map;

/**
 * http://www.finedevelop.com/pages/viewpage.action?pageId=18648778
 * 这是一个不被允许使用的类,配置文件都要求以单行的形式存储到数据库中,而不能使用直接存储xml文件
 * 目前的存在是属于过渡期,还有太多以前是xml格式序列化的对象没有办法一一更改
 */
@Deprecated
public class XmlHolders {
    //复杂Xmlable类型对象,其中包含其她复杂的对象,这样会影响很多其它业务对象,用这个包装器,这个包装器依赖readxml和writeXml
    //存储格式是 假设当前对象的父空间是config,property 是 arr ,存储格式为config.arr XXXXXX   xxx是这个xmlable对象的序列化结果
    @Deprecated
    @SuppressWarnings("unchecked")
    public static <T extends XMLable> Conf<T> obj(String property, T t, Class<T> clazz, String nameSpace) {
        return new XmlConf(property, t, clazz).setNameSpace(nameSpace);
    }

    @SuppressWarnings("unchecked")
    public static <T extends XMLable> Conf<T> obj(T t, Class<T> clazz) {
        return new XmlConf(t, clazz);
    }

    //复杂Xmlable类型对象集合,其中包含其她复杂的对象,这样会影响很多其它业务对象,用这个包装器,这个包装器依赖readxml和writeXml
    //存储格式是 假设当前对象的父空间是config,property 是 arr ,我会为集合中的对象随机分配一个id
    // 存储格式为config.arr.id XXXXXX   xxx是这个xmlable对象的序列化结果
    @Deprecated
    public static <T extends XMLable> XmlColConf<Collection<T>> collection(String property, Collection<T> t, Class<T> clazz, String nameSpace) {
        return new XmlColConf<Collection<T>>(property, t, clazz).setNameSpace(nameSpace);
    }

    public static <T extends XMLable> XmlColConf<Collection<T>> collection(Collection<T> t, Class<T> clazz) {
        return new XmlColConf<Collection<T>>(t, clazz);
    }

    //复杂Xmlable类型对象Map,其中包含其她复杂的对象,这样会影响很多其它业务对象,用这个包装器,这个包装器依赖readxml和writeXml
    ////存储格式是 假设当前对象的父空间是config,property 是 arr ,
    // 存储格式为config.arr.key XXXXXX   xxx是这个xmlable对象的序列化结果
    //K只能是基本类型或者字符串类型,又或者 K是一些简单的类型,这个不同的K对象可以转换成不同的String,注册K类型的ValueWriter对象,用来将K对象转换成String
    //同样 也要注册K类型的ValueReader,用来从String中恢复重新构造K对象
    @Deprecated
    public static <K, V extends XMLable> XmlMapConf<Map<K, V>> map(String property, Map<K, V> t, Class keyType, Class<V> clazz, String nameSpace) {
        return new XmlMapConf<Map<K, V>>(property, t, keyType, clazz).setNameSpace(nameSpace);
    }

    public static <K, V extends XMLable> XmlMapConf<Map<K, V>> map(Map<K, V> t, Class keyType, Class<V> clazz) {
        return new XmlMapConf<Map<K, V>>(t, keyType, clazz);
    }
}



以上所有用holder封装的Map的key只能是一些基本数据类型,八种基本类型的包装类型和String类型。又或者 K是一些简单的类型,这个不同的K对象可以转换成不同的String,注册K类型的ValueWriter对象,用来将K对象转换成String,ValueWriter.registerWriter,同样 也要注册K类型的ValueReader,用来从String中恢复重新构造K对象,ValueReader.registerReader。

  • No labels

1 Comment

  1. Anonymous

    这个配置文件和插件开发有什么关系