利用缓存机制快速读取XML文件中的数据

接到一个任务,让我做一个公司网站的后台管理系统。要求很简单,就一个新闻发布模块和一个招聘信息发布模块。但不能用DB,只能用文件存取的形式实现。

不用考虑肯定是用XML文件进行数据的存取了,以前做毕设的时候也曾经实现过类似的功能,所以关于XML的读取并没有问题。关键是如果考虑到性能的问题就值得推敲一下了,我是新人,以前也没做过什么设计,所以做出的东西在一些人眼中可能会有些稚嫩,那也没关系,走自己的路让别人去说吧:)

如果频繁解析文件,速度肯定受到影响,在文件非常大的情况下,甚至是无法忍受的。如果在服务器启动的时候先把文件中的数据封装成对象数组读入到缓存中,每次访问的时候先判断一下要访问的文件实体有没有被更新,如果没有被更新,就直接从缓存中将想要的数据读出来,当然如果文件被更新了,那只好老老实实的解析文件读出想要的数据。管理者对文件的修改次数毕竟是少数,更多的是访问者的访问次数。这样就能很大的提高了访问速度,代价是要占用一定的内存空间,但相比之下应该算小巫吧。

下面把简单实现的几个Class说一说。

一首先实现一个Cache类,里面有读取对象的方法get(),如果文件没有被修改则直接从HashMap里面将对象取出,如果文件被修改则调用readObject()方法实现从文件中读出数据,并同时将读出的数据放入HashMap里,将原来的对象覆盖。这样下次再读数据的时候就可以从缓存中直接读到,并且保证是最新的数据。还有一个判断文件是否被修改的方法getModified();
代码实现如下:

importjava.io.File;
importjava.util.HashMap;

publicclassCache{

HashMapmapLastModified=newHashMap();
HashMapmapValues=newHashMap();
publicCache(){
super();
}
publicObjectget(Stringname,Stringpath,ClassclsParser,ClassclsInstantiator,ClassclsObj){
Objectobj=null;
StringabsPath=getClass().getResource(path).getPath();
Longmodified=getModified(name,absPath);
if(modified!=null){
obj=readObject(absPath,clsParser,clsInstantiator,clsObj);

mapLastModified.put(name,modified);
mapValues.put(name,obj);
System.out.println("getobjectfromfile");
}else{
obj=mapValues.get(name);
System.out.println("getobjectfromcache");
}
returnobj;
}

privateLonggetModified(Stringname,Stringpath){
Longmodified=newLong(newFile(path).lastModified());
LongsaveModified=(Long)mapLastModified.get(name);
if((saveModified!=null)&&(saveModified.longValue()>=modified.longValue())){
modified=null;
}
returnmodified;
}

privateObjectreadObject(Stringpath,ClassclsParser,ClassclsInstantiator,ClassclsObj){
try{
FileParserparser=(FileParser)clsParser.newInstance();
Instantiatorinstantiator=(Instantiator)clsInstantiator.newInstance();

Objectconfig=parser.parse(path);
returninstantiator.instantiate(clsObj,config);

}catch(InstantiationExceptione){
e.printStackTrace();
}catch(IllegalAccessExceptione){
e.printStackTrace();
}
returnnull;
}
}

二解析XML文件的类XmlFileParser,
为了方便处理不同文件的解析,在这里先定义一个接口FileParser,XmlFileParser实现了它,如果还有诸如对其他种类文件的解析也可以实现它。
//FileParser.java
publicinterfaceFileParser{
Objectparse(Stringpath);

}

//XmlFileParser.java
//采用Jdom的解析方式

importjava.io.FileInputStream;
importjava.io.IOException;
importorg.jdom.Document;
importorg.jdom.Element;
importorg.jdom.input.SAXBuilder;

publicclassXmlFileParserimplementsFileParser{

publicXmlFileParser(){
super();
}

publicObjectparse(Stringpath){

FileInputStreamfi=null;
try{
fi=newFileInputStream(path);
SAXBuildersb=newSAXBuilder();
Documentdoc=sb.build(fi);
Elementroot=doc.getRootElement();
returnroot.getChildren();
}catch(Exceptione){
e.printStackTrace();
}finally{
try{
fi.close();
}catch(IOExceptione1){
}
}
}
}

三接下来是一个实例化处理的类ListTypeInstantiator,同样为了方便处理不同文件的实例化,在这里先定义一个接口Instantiator,ListTypeInstantiator实现了它。
//Instantiator.java
publicinterfaceInstantiator{
Objectinstantiate(Classclazz,Objectconfiguration);
}

//ListTypeInstantiator.java
importjava.util.ArrayList;
importjava.util.List;

importorg.apache.commons.beanutils.BeanUtils;
importorg.jdom.Element;

publicclassListTypeInstantiatorimplementsInstantiator{

publicListTypeInstantiator(){
super();
}

publicObjectinstantiate(Classclazz,Objectconfiguration){
Listarr=newArrayList();
Objectbean=null;

Listchildren=(List)configuration;
Elementchild=null;

Listattributes=null;
Elementattribute=null;

try{
for(inti=0;i<children.size();i++){
child=(Element)children.get(i);
bean=clazz.newInstance();
attributes=child.getChildren();
for(intj=0;j<attributes.size();j++){
attribute=(Element)attributes.get(j);
BeanUtils.setProperty(bean,attribute.getName(),attribute.getText());
}
arr.add(bean);
}
}catch(Exceptione){
e.printStackTrace();
}
returnarr;
}
}

四另外还需要一个封装我想要数据形式的JavaBean,这里设为NewsBean{}.
//NewsBean.java
publicclassNewsBean{

privateLongid;
privateStringnewsTitle;
privateStringnewsContent;
privateStringnewsType;
privateStringdeployDate;
privateStringcancelDate;

publicLonggetId(){
returnid;
}
publicvoidsetId(Longid){
this.id=id;
}
publicStringgetNewsTitle(){
returnnewsTitle;
}
publicvoidsetNewsTitle(StringnewsTitle){
this.newsTitle=newsTitle;
}
publicStringgetNewsContent(){
returnnewsContent;
}
publicvoidsetNewsContent(StringnewsContent){
this.newsContent=newsContent;
}
publicStringgetNewsType(){
returnnewsType;
}
publicvoidsetNewsType(StringnewsType){
this.newsType=newsType;
}
publicStringgetDeployDate(){
returndeployDate;
}
publicvoidsetDeployDate(StringdeployDate){
this.deployDate=deployDate;
}
publicStringgetCancelDate(){
returncancelDate;
}
publicvoidsetCancelDate(StringcancelDate){
this.cancelDate=cancelDate;
}
}

五最后一步测试结果,将news.xml文件放到classes目录下。
//MainClass.java

importjava.util.List;
publicclassMainClass{

publicstaticvoidmain(String[]args)throwsException{

Listnews1=null;
Listnews2=null;
NewsBeanbean=null;

news1=(List)Cache.get(
"news","/news.xml",
XmlFileParser.class,ListTypeInstantiator.class,NewsBean.class);
for(inti=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());
}
news2=(List)Cache.get(
"news","/news.xml",
XmlFileParser.class,ListTypeInstantiator.class,NewsBean.class);
for(inti=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());
}
}
第一次会从文件中读出数据,第二次就会从缓存中读取了,试着多读几次速度明显快很多。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值