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

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

2014-03-26 11:26 337 查看
http://blog.csdn.net/hingwu/article/details/1497892

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