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