隨筆 - 32, 文章 - 1, 評論 - 5, 引用 - 0
          數據加載中……

          利用Java反射讀取XML配置文件

          背景:項目配置文件分散,有FTP、文件格式、數據庫等。且單個任務配置都不一樣。故有了統一配置文件的想法,由統一的工具類生成配置對象。

          使用:dom4j,Java ioc

          首先是XML文件的定義,懶得寫schema,直接手寫了。配置項由于很多,且分類明確,所以一開始就打算將其分為多個Java類配置。

           1<?xml version="1.0" encoding="UTF-8"?>
           2<Config id="STAT1">
           3    <Stat>
           4        <Property name="configName" value="custconfig" />
           5        <Property name="descrption" value="企業信息處理" />
           6        <Property name="taskType" value="1" />
           7        <Property name="expiredMonth" value="6" />
           8        <Property name="batchNum" value="500" />
           9    </Stat>
          10    <Ftp>
          11        <Property name="host" value="127.0.0.1" />
          12        <Property name="user" value="stateg"/>
          13        <Property name="password" value="stateg"/>
          14        <Property name="port" value="14147"/>
          15        <Property name="remoteDir" value="/cust"/>
          16        <Property name="localDir" value="D:/ldata_eg/cu-udr"/>
          17        <Property name="fileNamePattern" value="CUST_\d{6}.TXT"/>
          18        <Property name="interval" value="10"/>
          19        <Property name="reserve" value="true"/>
          20        <Property name="maxFileCount" value="100"/>
          21        <Property name="checkInterval" value="7200"/>
          22    </Ftp>
          23    <Table>
          24        <Record>
          25            <Property name="tablename" value="T_CU_TABLE_NAME" />
          26            <Property name="separator" value=" " />
          27            <Property name="startrow" value="1" />
          28            <Property name="endCol" value="5" />
          29        </Record>
          30        <Column order="0" prop="ID" type="VARCHAR2" length="32" key="yes" />
          31        <Column order="1" prop="CUSTNAME" type="VARCHAR2" length="128" emtpy="yes" />
          32        <Column order="2" prop="CUSTAREA" type="VARCHAR2" length="128" emtpy="yes" />
          33        <Column order="3" prop="CREATEDATE" type="DATE"/>
          34        <Column order="4" prop="PARENTID" type="VARCHAR2" length="32" emtpy="yes" />
          35        <Column order="4" prop="UPDATETIME" type="DATE"/>
          36    </Table>
          37</Config>
          38


          接下來,就是XML文件的讀取了。使用dom4j是無疑的,可參見http://www.aygfsteel.com/colorfire/articles/338764.html。

           1/**
           2     * 獲取配置對象
           3     * @return
           4     * @throws DocumentException
           5     */

           6    public StatConfig getConfigInfo() throws DocumentException {
           7        SAXReader saxReader = new SAXReader();
           8        Document document = saxReader.read("META-INFO/xml/StatConfigInfo.xml");
           9
          10        // 配置入庫參數
          11        StatConfig statConfig = (StatConfig) reflectConfig(warpPropertyMap(document
          12                .selectNodes("//Config/Stat/Property")), StatConfig.class);
          13
          14        // 配置FTP客戶端參數
          15        FtpConfig ftpConfig = (FtpConfig) reflectConfig(warpPropertyMap(document.selectNodes("//Config/Ftp/Property")),
          16                FtpConfig.class);
          17
          18        // 配置數據庫
          19        TableConfig tableConfig = (TableConfig) reflectConfig(warpPropertyMap(document
          20                .selectNodes("//Config/Table/Record/Property")), TableConfig.class);
          21        List list = document.selectNodes("//Config/Table/Column");
          22        Iterator iter = list.iterator();
          23        Map<String, ColumnType> colMap = new HashMap<String, ColumnType>();
          24        while (iter.hasNext()) {
          25            Element element = (Element) iter.next();
          26            Map<String, String> configMap = warpAttributeMap(element.attributeIterator());
          27            ColumnType colum = (ColumnType) reflectConfig(configMap, ColumnType.class);
          28            colMap.put(Integer.toString(colum.getOrder()), colum);
          29        }

          30        tableConfig.setColMap(colMap);
          31
          32        statConfig.setFtpConfig(ftpConfig);
          33        statConfig.setTableConfig(tableConfig);
          34        return statConfig;
          35    }

          由于XML分塊,將數據封裝單獨抽取成方法。

          1private Map<String, String> warpPropertyMap(List list) {
          2        Map<String, String> configMap = new HashMap<String, String>();
          3        Iterator iter = list.iterator();
          4        while (iter.hasNext()) {
          5            Element element = (Element) iter.next();
          6            configMap.put(element.attributeValue("name").toLowerCase(), element.attributeValue("value").toLowerCase());
          7        }

          8        return configMap;
          9    }

          最后就是將配置數據封裝進對象,這里用反射再合適不過了。

           1public Object reflectConfig(Map<String, String> configMap, Class cls) {
           2        Object config = null;
           3        try {
           4            config = cls.newInstance();
           5            Field[] fields = cls.getDeclaredFields();
           6            for (int i = 0; i < fields.length; i++{
           7                String fieldName = fields[i].getName();
           8                Class fieldType = fields[i].getType();
           9                Method method = cls.getMethod("set" + genMethodName(fieldName), fieldType);
          10                String valueString;
          11                if ((valueString = configMap.get(fieldName.toLowerCase())) != null{
          12                    if (fieldType.equals(String.class)) {
          13                        method.invoke(config, valueString);
          14                    }
           else if (fieldType.equals(Integer.class)) {
          15                        method.invoke(config, Integer.parseInt(valueString));
          16                    }
           else if (fieldType.equals(Long.class)) {
          17                        method.invoke(config, Long.parseLong(valueString));
          18                    }
           else if (fieldType.equals(Boolean.class)) {
          19                        method.invoke(config, Boolean.parseBoolean(valueString));
          20                    }
           else if (fieldType.equals(Character.class)) {
          21                        method.invoke(config, valueString.toCharArray()[0]);
          22                    }
           else {
          23                        throw new NoSuchFieldException("FtpConfig沒有定義的數據類型");
          24                    }

          25                }

          26            }

          27        }
           catch (Exception e) {
          28            e.printStackTrace();
          29        }

          30        return config;
          31    }

          完成,想測試一下,單獨寫個測試方法吧。
           1/**
           2     * 測試方法
           3     * @param obj
           4     * @return
           5     */

           6    public static StringBuffer testPOJO(Object obj) {
           7        Class cls = obj.getClass();
           8        Field[] fields = cls.getDeclaredFields();
           9        StringBuffer resultBuf = new StringBuffer();
          10        try {
          11            for (int i = 0; i < fields.length; i++{
          12                String fieldName = fields[i].getName();
          13                Class fieldType = fields[i].getType();
          14                Method method;
          15                if (fieldType.equals(Boolean.class)) {
          16                    method = cls.getMethod("is" + genMethodName(fieldName));
          17                }
           else {
          18                    method = cls.getMethod("get" + genMethodName(fieldName));
          19                }

          20                Object res;
          21                if ((res = method.invoke(obj)) != null{
          22                    String result = res.toString();
          23                    resultBuf.append("[" + fieldName + "] = " + result + "\n");
          24                }
           else {
          25                    resultBuf.append("[" + fieldName + "] = NULL \n");
          26                }

          27            }

          28        }
           catch (Exception e) {
          29            e.printStackTrace();
          30        }

          31        return resultBuf;
          32    }


          總結:本來考慮的是統一配置后,丟棄ibatis,直接動態生成sql語句執行。但字段名與類屬性值匹配又是個麻煩,這里用反射的話就太影響性能了。沒想出好方法,再考慮考慮。
          后續把測試類改成遞歸的。

          posted on 2010-11-23 17:17 colorfire 閱讀(794) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 张家口市| 广宗县| 泉州市| 弥勒县| 锡林郭勒盟| 洛南县| 永仁县| 三河市| 福建省| 万山特区| 高清| 绥江县| 汾西县| 安国市| 友谊县| 鹤山市| 叙永县| 阳春市| 兰溪市| 常山县| 定远县| 漾濞| 永川市| 九龙县| 湖州市| 吉木萨尔县| 浑源县| 巧家县| 鄂伦春自治旗| 苏尼特右旗| 马边| 卢氏县| 香格里拉县| 合肥市| 古蔺县| 汶川县| 布尔津县| 南京市| 渑池县| 孟津县| 兰州市|