zoukankan      html  css  js  c++  java
  • 利用Java反射机制完成XML到对象的解析

    对于一些小批量的数据,如果采用数据库来存取的话,未免有点大题小作,使用XML文件是个不错的方法,尤其是在一些Web应用中,经常需要缓存一部分数据,如果将这些数据形成XML文件,解析后放入一个Hashtable,那就能大大加快访问的速度。

    由于工作的需要,写了一个解析工具,将XML解析成相应的对象列表。以下是源代码,希望对大家有所帮助,更希望大家帮我来改进这个工具。

    package com.sp.util;
    
    /*
     *    author:hingwu
     *  email:hing3@163.com
     *  QQ:550598
     *  MSN:hing3wu@hotmail.com(很少开) 
    */
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.NodeList;
    
    import exceptions.MyException;
    
    public class ParseXMLToObject {
        public ParseXMLToObject(){}
        
        @SuppressWarnings("unchecked")
        public List getObject(String name,String path,String className){
            DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
            dbf.setIgnoringElementContentWhitespace(true);
            DocumentBuilder db=null;
            Document doc=null;
            InputStream is=null;
            try {
                List list=new ArrayList();
                db=dbf.newDocumentBuilder();
                is=new FileInputStream(this.getClass().getResource(path).getPath());
                doc=db.parse(is);
                //根据要取的对象名称获取相应的节点列表
                NodeList nodes=doc.getElementsByTagName(name);
                if(nodes==null){
                    throw new MyException("null nodes with tagName "+name);
                }
                for(int i=0;i<nodes.getLength();i++){
                    Element node=(Element) nodes.item(i);
                    Class cls=Class.forName(className);
                    Object obj=cls.newInstance();
                    //获取节点下的所有子节点
                    NodeList childs=node.getChildNodes();
                    if(childs==null){
                        throw new MyException("null childs! "+node);
                    }
                    for(int j=0;j<childs.getLength();j++){
                        if(!childs.item(j).getNodeName().equals("#text")){
                            Element child=(Element)childs.item(j);
                            String childName=child.getNodeName();
                            String type=child.getAttribute("type");
                            String value=child.getAttribute("value");
                            Object valueObj=typeConvert(type,value);
                            String methodName="set"+Character.toUpperCase(childName.charAt(0))+childName.substring(1);
                            System.out.println("methodName="+methodName+", class="+Class.forName(type));
                            Method method=cls.getMethod(methodName, Class.forName(type));
                            method.invoke(obj, new Object[]{valueObj});
                        }
    
                    }
                    list.add(obj);
                }
                return list;
                
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return null;
            }
    
        }
        

        
    //此方法用于将一个字符串转换为相应的数据类型
        @SuppressWarnings("deprecation")
        public Object typeConvert(String className,String value){
            if(className.equals("java.lang.String")){
                return value;
            }
            else if(className.equals("java.lang.Integer")){
                return Integer.valueOf(value);
            }
            else if(className.equals("java.lang.Long")){
                return Long.valueOf(value);
            }
            else if(className.equals("java.lang.Boolean")){
                return Boolean.valueOf(value);
            }
            else if(className.equals("java.util.Date")){
                return new Date(value);
            }
            else if(className.equals("java.lang.Float")){
                return Float.valueOf(value);
            }
            else if(className.equals("java.lang.Double")){
                return Double.valueOf(value);
            }else return null;
        }
    }
    
    Subject类的代码:
    
    package com.sp.pojo;
    
    public class Subject {
        private String port;
        private String servletName;
        public String getPort() {
            return port;
        }
        public void setPort(String port) {
            this.port = port;
        }
        public String getServletName() {
            return servletName;
        }
        public void setServletName(String servletName) {
            this.servletName = servletName;
        }
        public Subject(){}
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return port+","+servletName;
        }
        
    }
    附上我的XML文件
    
    <?xml version="1.0" encoding="UTF-8"?>
    <xml-body>
        <subjects>
            <port type="java.lang.String" value="4587"/>
            <servletName type="java.lang.String" value="com.sp.servlets.Route" />
        </subjects>
        
        <subjects>
            <port type="java.lang.String" value="5687"/>
            <servletName type="java.lang.String" value="com.sp.servlets.Route" />
        </subjects>
        
        <security>
            <userName type="java.lang.String" value="gogo"/>
            <password type="java.lang.String" value="gogo" />    
        </security>
    </xml-body>
    
     
    
     
    
    自己写了一个测试类进行测试
    
     
    
    /**
     *    author:hingwu
     *  email:hing3@163.com
     *  QQ:550598
     *  MSN:hing3wu@hotmail.com(很少开) 
     *
     * 上午11:44:27
     */
    package com.sp.test;
    
    import java.util.Iterator;
    import java.util.List;
    
    import com.sp.util.ParseXMLToObject;
    
    public class TestParse {
        public static void main(String[] args){
            ParseXMLToObject pxt=new ParseXMLToObject();
    //        List list=(List)pxt.getObject("security","/cache.xml","com.sp.pojo.Security");
            List list=(List)pxt.getObject("subjects","/cache.xml","com.sp.pojo.Subject");
            Iterator it=list.iterator();
            while(it.hasNext()){
                System.out.println(it.next());
            }
    
            
        }
    }
    
     
    
    由于我的这个工具主要是为了缓存数据来使用的,我同时还完成了缓存类Cache的代码:
    
     
    
    package com.sp.util;
    
    
    import java.io.File;
    import java.util.Hashtable;
    
    public class Cache {
        //cache用来放置各种需要缓存的数据
        private static Hashtable cache=new Hashtable();
        //lastModifyTime用于维护配置文件的最后修改时间,从而确定是直接从Cache读数据还是需要重新解析配置文件
        private static long lastModifyTime;
        
        public Object getObject(String name,String path,String parseClass,String className){
            //如果配置文件被修改过则直接解析文件,否则直接从cache中取得相应的对象
            if(checkModifyTime(path)){
                System.out.println("get Object from file");
                return getObjectFromFile(name,path,className);
            }
            return getObjectFromCache(name);
        }
        
        //直接从缓存中获取相应的对象
        public Object getObjectFromCache(String name){
            System.out.println("get Object from cache");
            return cache.get(name);
        }
        
        //解析配置文件获取相应的对象
        @SuppressWarnings("unchecked")
        public Object getObjectFromFile(String name,String path,String className){
            String key="key";
            synchronized(key){
                ParseXMLToObject pxt=new ParseXMLToObject();
                Object obj=pxt.getObject(name, path, className);
                cache.put(name, obj);
                return obj;
            }
    
        }
        
        
        //判断配置文件是否被修改过
        public boolean checkModifyTime(String path){
            String absPath=this.getClass().getResource(path).getPath();
            long time=(new File(absPath)).lastModified();
            if(lastModifyTime==0L||time>lastModifyTime){
                lastModifyTime=time;
                return true;
            }
            return false;
        }
    }
    
     
    
    每次通过Cache去获取Hashtable中的数据时,会先判断XML文件有没有被修改过,如果没有修改,则直接返回数据,有修改则解析XML文件后返回数据。
    
    为了测试Cache类,专门写了一个Test类:
    
     
    
    /**
     *    author:hingwu
     *  email:hing3@163.com
     *  QQ:550598
     *  MSN:hing3wu@hotmail.com(很少开) 
     *
     * 下午02:04:10
     */
    package com.sp.test;
    import java.util.Iterator;
    import java.util.List;
    
    import com.sp.util.Cache;
    
    public class TestCache {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            for(int i=0;i<10;i++){
                System.out.println("第"+i+"次获取缓存数据:");
                Cache cache=new Cache();
                List list=(List)cache.getObject("subjects","/cache.xml", "com.sp.util.ParseXMLToObject", "com.sp.pojo.Subject");
                Iterator it=list.iterator();
                while(it.hasNext()){
                    System.out.println(it.next());
                }
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
    
        }
    
    }
    
    这种缓存策略有个好处,那就是在应用运行的时候,我们可以随时修改XML文件,而不需要重启应用或重新布署。
  • 相关阅读:
    简单的 canvas 翻角效果
    浏览器中 大部分API
    @description iPhoneX炫彩渐变背景实现
    Vuex
    百度地图 逆地址解析
    android上传位置信息导致的流量大爆炸问题调查
    在win7下装ubuntu(硬盘版安装)及遇到的问题
    Android程序捕获未处理异常,处理与第三方方法冲突时的异常传递
    apk混淆打包注意事项
    IdeasToComeTrue
  • 原文地址:https://www.cnblogs.com/mgzy/p/3862441.html
Copyright © 2011-2022 走看看