飛艷小屋

          程序--人生--哲學(xué)___________________歡迎艷兒的加入

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            52 Posts :: 175 Stories :: 107 Comments :: 0 Trackbacks
          利用緩存機(jī)制快速讀取XML文件中的數(shù)據(jù)

                 接到一個(gè)任務(wù),讓我做一個(gè)公司網(wǎng)站的后臺(tái)管理系統(tǒng)。要求很簡(jiǎn)單,就一個(gè)新聞發(fā)布模塊和一個(gè)招聘信息發(fā)布模塊。但不能用DB,只能用文件存取的形式實(shí)現(xiàn)。

                 不用考慮肯定是用XML文件進(jìn)行數(shù)據(jù)的存取了,以前做畢設(shè)的時(shí)候也曾經(jīng)實(shí)現(xiàn)過類似的功能,所以關(guān)于XML的讀取并沒有問題。關(guān)鍵是如果考慮到性能的問題就值得推敲一下了,我是新人,以前也沒做過什么設(shè)計(jì),所以做出的東西在一些人眼中可能會(huì)有些稚嫩,那也沒關(guān)系,走自己的路讓別人去說吧:)

                 如果頻繁解析文件,速度肯定受到影響,在文件非常大的情況下,甚至是無法忍受的。如果在服務(wù)器啟動(dòng)的時(shí)候先把文件中的數(shù)據(jù)封裝成對(duì)象數(shù)組讀入到緩存中,每次訪問的時(shí)候先判斷一下要訪問的文件實(shí)體有沒有被更新,如果沒有被更新,就直接從緩存中將想要的數(shù)據(jù)讀出來,當(dāng)然如果文件被更新了,那只好老老實(shí)實(shí)的解析文件讀出想要的數(shù)據(jù)。管理者對(duì)文件的修改次數(shù)畢竟是少數(shù),更多的是訪問者的訪問次數(shù)。這樣就能很大的提高了訪問速度,代價(jià)是要占用一定的內(nèi)存空間,但相比之下應(yīng)該算小巫吧。

                  下面把簡(jiǎn)單實(shí)現(xiàn)的幾個(gè)Class說一說。

                  一 首先實(shí)現(xiàn)一個(gè)Cache類,里面有讀取對(duì)象的方法get(),如果文件沒有被修改則直接從HashMap里面將對(duì)象取出,如果文件被修改則調(diào)用readObject()方法實(shí)現(xiàn)從文件中讀出數(shù)據(jù),并同時(shí)將讀出的數(shù)據(jù)放入HashMap里,將原來的對(duì)象覆蓋。這樣下次再讀數(shù)據(jù)的時(shí)候就可以從緩存中直接讀到,并且保證是最新的數(shù)據(jù)。還有一個(gè)判斷文件是否被修改的方法getModified();
          代碼實(shí)現(xiàn)如下:

          import java.io.File;
          import java.util.HashMap;

          public class Cache {
             
              HashMap mapLastModified = new HashMap();
              HashMap mapValues = new HashMap();
              public Cache() {
                  super();
              }   
              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,
          為了方便處理不同文件的解析,在這里先定義一個(gè)接口FileParser,XmlFileParser實(shí)現(xiàn)了它,如果還有諸如對(duì)其他種類文件的解析也可以實(shí)現(xiàn)它。
          //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) {
           
            FileInputStream fi = null;
            try {
             fi = new FileInputStream(path);
             SAXBuilder sb = new SAXBuilder();
             Document doc = sb.build(fi);
             Element root = doc.getRootElement();
             return root.getChildren();
            } catch (Exception e) {
             e.printStackTrace();
            } finally {
             try {
              fi.close();
             } catch (IOException e1) {
             }
            } 
           }
          }

          三 接下來是一個(gè)實(shí)例化處理的類ListTypeInstantiator,同樣為了方便處理不同文件的實(shí)例化,在這里先定義一個(gè)接口Instantiator,ListTypeInstantiator實(shí)現(xiàn)了它。
          //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;
           }
          }

          四 另外還需要一個(gè)封裝我想要數(shù)據(jù)形式的JavaBean,這里設(shè)為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;
           }
          }

          五 最后一步測(cè)試結(jié)果,將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.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());
            }
            news2 = (List)Cache.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());
            }
          }
          第一次會(huì)從文件中讀出數(shù)據(jù),第二次就會(huì)從緩存中讀取了,試著多讀幾次速度明顯快很多。
           

          posted on 2005-12-03 15:03 天外飛仙 閱讀(183) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 永安市| 中卫市| 清远市| 平乡县| 额尔古纳市| 四子王旗| 定远县| 盐津县| 衡水市| 天全县| 探索| 神池县| 尚志市| 徐汇区| 上高县| 呼玛县| 平南县| 蓬莱市| 建昌县| 陵水| 兴仁县| 桃江县| 枣庄市| 永济市| 绿春县| 安徽省| SHOW| 高州市| 安义县| 禄丰县| 松原市| 年辖:市辖区| 浠水县| 环江| 澄迈县| 侯马市| 安仁县| 洱源县| 柞水县| 黔南| 鄯善县|