偶的数据字典(XML),不使用数据库

本文介绍了一种不依赖数据库的数据字典管理方案,通过XML文件存储键值对,并利用Java代码在系统启动时加载到内存中,方便后续使用。
我这里设计的数据字典并非是数据库的数据字典,而是在项目编码过程中涉及到一些类似字典查询的操作。

需求:

     在项目开发中,一些变量需要在多个地方使用,但这些变量的值是在某一范围内,且每一个值对应一个翻译的字面量。

?0?1  若是使用数据库存储,因为变量值是固定的,多余的数据库访问没有必要;

?0?1  若是直接硬编码到代码中,若是需要进行修改的时候,造成维护困难;

?0?1  若是以常量方式书写到类中并在使用时引用,你将发现你的常量类Constants里面内容庞杂,命名和使用都极其困难。

 

常见此类键值对如:

    1.省代码表,省编码对应一个描述信息。

    2.婚姻码表,例如1:单身, 2:未婚, 3:离异, 4:已婚, 5:恋爱中等。

    3.教育码表,例如1:初中, 2:高中, 3:大专, 4:本科, 5:硕士, 6:博士等。

     .........

    这类键值对特点:在库中存储的是数字或字母编码,但在展示的时候使用的却是其文本内容


处理方式

       1. 将键值对内容书写到XML文件中。

    2.系统启动时读取加载入内存

    3.使用时直接调用翻译 。


实现:

      需要的xml文件(dics.xml),你可以自己定义:

    

<?xml version="1.0" encoding="UTF-8"?>
    <dics>
        <t id="marry"><!-- id是一个标识而已 -->
    <r v="1">单身</r>
    <r v="2">离异</r>
    <r v="3>已婚</r>
    <r v="4">恋爱中</r>
</t>
        <t id="edu">
    <r v="1">初中</r>
    <r v="2">高中</r>
    <r v="3">大专</r>
    <r v="4">本科</r>
    <r v="5">硕士</r>
    <r v="6">博士</r>
</t>
    </dics>

    Java代码,偶是利用Dom4j来处理xml文件,其中包含ClsLoader类,这个是一个工具类,我用来加载项目中的配置文件(包括WEB目录和类路径目录);

    加载dics.xml文件,解析完成后,用HashMap缓存

     

public abstract class Dict {
            /**缓存数据字典,如此使用:dics.get("marry");获取的是marry的字典数据,取某个文本:dics.get("marry").get("1")获取的就是“单身”文本,你可以自己定义一个方法,专门来获取*/
    public static final Map<String,LinkedHashMap<String,String>> dics=new HashMap<String, LinkedHashMap<String, String>>();
    /**
     * 初始化数据字典,一般在过滤器或者servlet中的init方法中调用
     */
    public static void init(){
        SAXReader reader=new SAXReader();
        try {
            Document doc=reader.read(ClsLoader.getStream("dics.xml"));
            Element root=doc.getRootElement();
            for(Iterator<Element> ite=root.elementIterator("t");ite.hasNext();){
                Element et=ite.next();
                dics.put(et.attributeValue("id"),handT(et));//handT这个方法处理T下面的r元素
            }
            doc=null;root=null;
        } catch (DocumentException e) {
            throw new SysException("解析常量的XML文件出错!",e);
        } catch (IOException e) {
            throw new SysException("读取常量的XML文件出错!",e);
        }
        reader=null;
    }

    /**
     * 处理R
     * @param e 元素
     * @return 元素下的r集合
     */
    public static LinkedHashMap<String,String> handT(Element e){
        LinkedHashMap<String,String> rs=new LinkedHashMap<String, String>();
        for(Iterator<Element> er =e.elementIterator("r");er.hasNext();){
            Element ers=er.next();
            rs.put(ers.attributeValue("v"),ers.getText());
        }
        return rs;
    }

    /**
     * web系统结束是销毁内存中的数据,一般在过滤器或者servlet 的destroy中调用
     */
    public static void destroy(){
        for(Map.Entry<String, LinkedHashMap<String,String>> entry:dics.entrySet()){
            LinkedHashMap<String,String> m=entry.getValue();
            m.clear();m=null;
        }
        dics.clear();
    }
    public static void main(String[] args)
    {
        long s=System.currentTimeMillis();
        init();
        System.out.println(dics.get("marry"));
        System.out.println(dics.get("edu"));
        System.out.println("耗时:"+(System.currentTimeMillis()-s));
        destroy();
    }
}

那在你的JSP或者Freemarker中怎么使用呢?我用的是Freemarker,以Freemarker为例:

首先自定义 一个Freemaker的方法,Freemarker方法的自定义类如下:

public class DictDic implements TemplateMethodModel {

    @Override
    public Object exec(List args) throws TemplateModelException {
        int size=args.size();
        String k=(String)args.get(0);
        if(size==1) return dics.get(k);//参数长度为1的时候获取的是指定类型的HashMap,例如 在ftl模板中调用${dict('marry')}
        if(size==2){
            String v=(String)args.get(1);//参数长度为2的时候获取的是单个文本值,例如 在ftl模板中调用${dict('marry','2')}==离异
            return dics.get(k).get(v);
        }
        return null;
    }
} 


将这个类注册到Freemarker的上下文中,这里给出Spring中的注册: 

<bean id="dict" class="tqw.dic.DictDic"/><!--定义-->

<!-- Freemarker视图 配置 -->

   <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">

        <property name="freemarkerVariables">

            <map>

                <entry key="dict" value-ref="dict"/><!--在这里注册-->

            </map>

        </property>

        <property name="templateLoaderPath" value="/WEB-INF"/>

        <property name="freemarkerSettings">

            <props>

                <prop key="tag_syntax">square_bracket</prop>

                <prop key="template_update_delay">0</prop>

                <prop key="defaultEncoding">UTF-8</prop>

                <prop key="url_escaping_charset">UTF-8</prop>

                <prop key="locale">zh_CN</prop>

                <prop key="boolean_format">true,false</prop>

                <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>

                <prop key="date_format">yyyy-MM-dd</prop>

                <prop key="time_format">HH:mm:ss</prop>

                <prop key="number_format">0.######</prop>

                <prop key="classic_compatible">false</prop>

                <prop key="whitespace_stripping">true</prop>

          </props>

      </property>

  </bean>

 最后就是使用了,例如在frl模板中这么使用:  ${dict("edu","1")},${dict("marry","1")},其余的自己扩展吧,欢迎拍砖~!!!!


Over~!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值