对于一些小批量的数据,如果采用数据库来存取的话,未免有点大题小作,使用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;
}
}
/**/ /*
* 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;
}
}
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 >
< 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());
}
}
}
* 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;
}
}
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();
}
}
}
}
* 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文件,而不需要重启应用或重新布署。