一 、首先实现一个Cache类,里面有读取对象的方法get(),如果文件没有被修改则直接从HashMap里面将对象取出,如果文件被修改则调用readObject()方法实现从文件中读出数据,并同时将读出的数据放入HashMap里,将原来的对象覆盖。这样下次再读数据的时候就可以从缓存中直接读到,并且保证是最新的数据。还有一个判断文件是否被修改的方法getModified();
import java.io.File; import java.util.HashMap; public class Cache { private static Cache instance; HashMap mapLastModified = new HashMap(); HashMap mapValues = new HashMap(); private Cache() { super(); } public static Cache getInstance() { if (instance == null) instance = new Cache(); return instance; } public Object get(String name, String path, Class clsParser, Class clsInstantiator, Class clsObj) { Object obj = null; String absPath = getClass().getResource(path).getPath(); Long modified = getModified(name, absPath); if (modified != null) { obj = readObject(absPath, clsParser, clsInstantiator, clsObj); mapLastModified.put(name, modified); mapValues.put(name, obj); System.out.println("get object from file"); } else { obj = mapValues.get(name); System.out.println("get object from cache"); } return obj; } private Long getModified(String name, String path) { Long modified = new Long(new File(path).lastModified()); Long saveModified = (Long) mapLastModified.get(name); if ((saveModified != null) && (saveModified.longValue() >= modified.longValue())) { modified = null; } return modified; } private Object readObject(String path, Class clsParser, Class clsInstantiator, Class clsObj) { try { FileParser parser = (FileParser) clsParser.newInstance(); Instantiator instantiator = (Instantiator) clsInstantiator.newInstance(); Object config = parser.parse(path); return instantiator.instantiate(clsObj, config); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; } }
二、 解析XML文件的类XmlFileParser,
为了方便处理不同文件的解析,在这里先定义一个接口FileParser,XmlFileParser实现了它,如果还有诸如对其他种类文件的解析也可以实现它。
//FileParser.java
public interface FileParser {
Object parse(String path);
}
//XmlFileParser.java
//采用Jdom的解析方式
import java.io.FileInputStream; import java.io.IOException; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; public class XmlFileParser implements FileParser { public XmlFileParser() { super(); } public Object parse(String path) { Element root=null; FileInputStream fi = null; try { fi = new FileInputStream(path); SAXBuilder sb = new SAXBuilder(); Document doc = sb.build(fi); root= doc.getRootElement(); } catch (Exception e) { e.printStackTrace(); } finally { try { fi.close(); } catch (IOException e1) { } } return root.getChildren(); } }
三 接下来是一个实例化处理的类ListTypeInstantiator,同样为了方便处理不同文件的实例化,在这里先定义一个接口Instantiator,ListTypeInstantiator实现了它。
//Instantiator.java
public interface Instantiator {
Object instantiate(Class clazz, Object configuration);
}
//ListTypeInstantiator.java
import java.util.ArrayList; import java.util.List; import org.apache.commons.beanutils.BeanUtils; import org.jdom.Element; public class ListTypeInstantiator implements Instantiator { public ListTypeInstantiator() { super(); } public Object instantiate(Class clazz, Object configuration) { List arr = new ArrayList(); Object bean = null; List children = (List) configuration; Element child = null; List attributes = null; Element attribute = null; try { for(int i=0; i< children.size(); i++) { child = (Element) children.get(i); bean = clazz.newInstance(); attributes = child.getChildren(); for(int j=0; j< attributes.size(); j++) { attribute = (Element) attributes.get(j); BeanUtils.setProperty(bean, attribute.getName(), attribute.getText()); } arr.add(bean); } } catch(Exception e) { e.printStackTrace(); } return arr; } }
四 另外还需要一个封装我想要数据形式的JavaBean,这里设为NewsBean{}.
//NewsBean.java
public class NewsBean { private Long id; private String newsTitle; private String newsContent; private String newsType; private String deployDate; private String cancelDate; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getNewsTitle() { return newsTitle; } public void setNewsTitle(String newsTitle) { this.newsTitle = newsTitle; } public String getNewsContent() { return newsContent; } public void setNewsContent(String newsContent) { this.newsContent = newsContent; } public String getNewsType() { return newsType; } public void setNewsType(String newsType) { this.newsType = newsType; } public String getDeployDate() { return deployDate; } public void setDeployDate(String deployDate) { this.deployDate = deployDate; } public String getCancelDate() { return cancelDate; } public void setCancelDate(String cancelDate) { this.cancelDate = cancelDate; } }
五 最后一步测试结果,将news.xml文件放到classes目录下。
//MainClass.java
import java.util.List; public class MainClass{ public static void main(String[] args) throws Exception { List news1 = null; List news2 = null; NewsBean bean = null; news1 = (List)Cache.getInstance().get("news", "/news.xml", XmlFileParser.class, ListTypeInstantiator.class, NewsBean.class); for (int i = 0; i < news1.size(); i++) { bean = (NewsBean) news1.get(i); System.out.println(bean.getId()); System.out.println(bean.getNewsTitle()); System.out.println(bean.getNewsContent()); System.out.println(bean.getNewsType()); System.out.println(bean.getDeployDate()); System.out.println(bean.getCancelDate()); } System.out.println("Ok"); news2 = (List)Cache.getInstance().get("news", "/news.xml", XmlFileParser.class, ListTypeInstantiator.class, NewsBean.class); for (int i = 0; i < news2.size(); i++) { bean = (NewsBean) news2.get(i); System.out.println(bean.getId()); System.out.println(bean.getNewsTitle()); System.out.println(bean.getNewsContent()); System.out.println(bean.getNewsType()); System.out.println(bean.getDeployDate()); System.out.println(bean.getCancelDate()); } } }
第一次会从文件中读出数据,第二次就会从缓存中读取了,试着多读几次速度明显快很多。
测试的news.xml文件
<?xml version="1.0" encoding="gb2312"?>
<javanews>
<news>
<id>1</id>
<newsTitle>jdk1.5 API 中文版</newsTitle>
<newsContent>赶快下载</newsContent>
<newsType>news</newsType>
<deployDate>2005-11-30</deployDate>
<cancelDate>2006-1-30</cancelDate>
</news>
<news>
<id>2</id>
<newsTitle>java RPG 游戏</newsTitle>
<newsContent>赶快下载</newsContent>
<newsType>news</newsType>
<deployDate>2005-11-30</deployDate>
<cancelDate>2006-1-30</cancelDate>
</news>
</javanews>
运行结果:
C:\java>java MainClass
get object from file
news
1
jdk1.5 API 中文版
赶快下载
2005-11-30
2006-1-30
news
2
java RPG 游戏
赶快下载
2005-11-30
2006-1-30
Ok
news
get object from cache
1
jdk1.5 API 中文版
赶快下载
2005-11-30
2006-1-30
news
2
java RPG 游戏
赶快下载
2005-11-30
2006-1-30
C:\java>