您的位置:首页 > 编程语言 > Java开发

利用Java反射机制完成XML到对象的解析

2007-01-30 14:40 519 查看
对于一些小批量的数据,如果采用数据库来存取的话,未免有点大题小作,使用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文件,而不需要重启应用或重新布署。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: