隨筆-67  評(píng)論-522  文章-0  trackbacks-0
              目前XML文件的應(yīng)用越來越廣泛,而操作XML的技術(shù)更有不少,其中以dom4j強(qiáng)大的性能,豐富的API以及簡單的易用性,受到了很多人的喜愛,本文以一個(gè)讀取數(shù)據(jù)源的小例子,來說明一下dom4j的一些基本操作。
              dom4j一個(gè)JavaXML API,同時(shí)也是一種解析XML文檔的開源軟件。由dom4j.org開發(fā),具有性能優(yōu)異、功能強(qiáng)大和極端易用的特點(diǎn),大名鼎鼎的Hibernate就是用它來讀取配置文件滴。本文只是對(duì)dom4j的一些基本操作進(jìn)行說明,不包含深入分析。(本文最后有源碼和相關(guān)JAR包下載)
              開發(fā)環(huán)境:Eclipse 3.2.1 MyEclipse 5.1.0GA dom4j-1.6.1.jar jaxen-1.1-beta-7.jar
              1、創(chuàng)建Web Project
                 Web Project來演示的原因一是因?yàn)?span lang="EN-US">WEB-INF目錄下有一個(gè)lib目錄,例子中需要用到的jar包,直接放進(jìn)去就行了,二是這個(gè)系列后面講的內(nèi)容會(huì)需要。如果建Java Project則還要設(shè)置庫路徑,為了方便,就用Web Project吧。點(diǎn)擊"File"->"New"->"Project",選擇"Web Project",在"Project Name"中輸入demo,點(diǎn)擊"Finish"。然后我們把dom4j-1.6.1.jarjaxen-1.1-beta-7.jar還有MySQL的連接驅(qū)動(dòng)放到WEB-INF\lib目錄下。
              2、創(chuàng)建DBConnect.xml
                 src目錄下建一個(gè)DBConnect.xml文件,內(nèi)容如下:
          <?xml version="1.0" encoding="UTF-8"?>
          <demo>
              
          <database>
                  
          <driver>com.mysql.jdbc.Driver</driver>
                  
          <url>jdbc:mysql://127.0.0.1:3306/mysql</url>
                  
          <username>root</username>
                  
          <password>123</password>
              
          </database>
          </demo>
                 大象在這里用MySQL的數(shù)據(jù)庫,當(dāng)然你也可以換成SQL Server或是Oracle,不過XML文件中對(duì)應(yīng)的配置都要作相應(yīng)的改動(dòng)!
              3、創(chuàng)建DataBaseConnect.java
                 在src上點(diǎn)右鍵,選擇"New->Package",輸入:com.demo.database,在database下新建一個(gè)類,類名為:DataBaseConnect。下面我們先寫一段簡單的代碼,測試一下,看看能否從這個(gè)XML文件中讀取到配置信息。在DataBaseConnect類中加入main函數(shù),然后寫上如下代碼:
              public static void main(String[] args){
                  
          try{
                      SAXReader saxReader 
          = new SAXReader(); //使用SAXReader方式讀取XML文件
                      //加載數(shù)據(jù)庫XML配置文件,得到Document對(duì)象
                      Document document = saxReader.read(new File("src/DBConnect.xml")); 
                      Element root = document.getRootElement(); //獲得根節(jié)點(diǎn)
                      //得到database節(jié)點(diǎn)
                      Element database = (Element)root.selectSingleNode("//demo/database"); 
                      List list = database.elements(); //得到database元素下的子元素集合
                      /*
                       * 循環(huán)遍歷集合中的每一個(gè)元素
                       * 將每一個(gè)元素的元素名和值在控制臺(tái)中打印出來
                       
          */
                      
          for(Object obj:list){
                          Element element 
          = (Element)obj;
                          
          //getName()是元素名,getText()是元素值
                          System.out.println(element.getName()+""+element.getText());
                      }
                  }
          catch(Exception e){
                      e.printStackTrace();
                  }
              }
                 這里有三點(diǎn)要說明一下:
                   a、saxReader.read(new File("src/DBConnect.xml")),這個(gè)read方法是一個(gè)重載的方法,里面的參數(shù)可以為File、FileInputStream、URL等。所以這里還可以寫成new FileInputStream ("src/DBConnect.xml"),另外還可以用ClassLoader來加載:getClass().getClassLoader().getResourceAsStream("DBConnect.xml"),注意,這里不能加"src/",因?yàn)樗窃?/span>WEB-INF\classes里面找文件,另外不能寫在靜態(tài)的main函數(shù)里,可以在main方法外,創(chuàng)建一方法,在main中通過實(shí)例化類對(duì)象來調(diào)用,這里不再詳述,大家自己去試下。
                   b、root.selectSingleNode("http://demo/database"),這里的"http://demo/database"其實(shí)是一個(gè)XPATH語法,關(guān)于XPATH請(qǐng)參考相關(guān)資料,這里不作討論。這樣寫的意思是指:demo根節(jié)點(diǎn)下的database節(jié)點(diǎn),"selectSingleNode"是得到database這個(gè)單獨(dú)的元素,至于database下面是否還包含別的信息,則是通過其它的API來操作。
                    c、如果你在使用XPATH語法的時(shí)候沒有加入jaxen-1.1-beta-7.jar這個(gè)包,就會(huì)出現(xiàn)如下異常:
          Exception in thread "main" java.lang.NoClassDefFoundError: org/jaxen/JaxenException
              at org.dom4j.DocumentFactory.createXPath(DocumentFactory.java:230)
              at org.dom4j.tree.AbstractNode.createXPath(AbstractNode.java:207)
              at org.dom4j.tree.AbstractNode.selectSingleNode(AbstractNode.java:183)
              at com.demo.database.DataBaseConnect.main(DataBaseConnect.java:16)
                 如果沒有問題的話,應(yīng)該可以在控制臺(tái)看到下面的結(jié)果:
          driver: com.mysql.jdbc.Driver
          url: jdbc:mysql://127.0.0.1:3306/mysql
          username: root
          password: 
          123

                 到此,我們已經(jīng)成功使用dom4jXML中讀取文件,下面我們對(duì)DataBaseConnect作一下修改,畢竟上面這種寫法是測試用的,真正的類怎么可能這樣寫?
              4、創(chuàng)建ClassUtils.java
                 新建com.demo.util包,在util包下新建ClassUtils類,用來處理資源加載方面的事情,內(nèi)容如下:

              /*
               * 這里使用的是單態(tài)模式
               
          */
              
          private static ClassUtils instance = new ClassUtils(); //實(shí)例化私有靜態(tài)對(duì)象
              
              
          /**
               * 通過資源名稱或資源路徑得到資源輸入流
               * 
          @param name 資源名稱或資源路徑
               
          */
              
          public static InputStream getResourceAsStream(String name) {
                  
          /*
                   * 這里用到了回調(diào)方法
                   * 使用靜態(tài)的私有對(duì)象,在靜態(tài)方法中調(diào)用非靜態(tài)的方法
                   * 并且loadResource是私有方法,對(duì)外不可見
                   
          */
                  
          return instance.loadResource(name);
              }
              
              
          /**
               * 私有構(gòu)造函數(shù),不能在外部被實(shí)例化
               
          */
              
          private ClassUtils() {}
              
              
          /**
               * 通過資源名稱或資源路徑加載資源
               * 
          @param name 資源名稱或資源路徑
               * 
          @return InputStream
               
          */
              
          private InputStream loadResource(String name) {
                  
          return getClass().getClassLoader().getResourceAsStream(name);
              }
              5、創(chuàng)建Constant接口
                 在util包下再建一個(gè)Constant接口,里面放的是數(shù)據(jù)源配置常量字符串,與XML文件中的元素名對(duì)應(yīng),在這里是將DBConnect.xml放在src目錄下,如果你想放到其它的目錄下,則要加上包名,比如放在database包下,那么應(yīng)該寫成:com/demo/database/DBConnect.xml。
              String DRIVER = "driver";
              String URL 
          = "url";
              String USERNAME 
          = "username";
              String PASSWORD 
          = "password";
              String DB_CONFIG 
          = "DBConnect.xml";
                 在接口中,方法自動(dòng)定義成public的,域自動(dòng)的被定義為public、staticfinal的,因此不用顯式的聲明。
              6、修改DataBaseConnect
                 最后我們來修改DataBaseConnect類,首先我們定義幾個(gè)靜態(tài)變量:
              private static Element coreModel; //根元素
              private static String driver; //連接驅(qū)動(dòng)
              private static String url;    //數(shù)據(jù)庫連接地址
              private static String username; //用戶名
              private static String password; //密碼
                 讀取DBConnect.xml文件,獲得根元素:
              /**
               * 加載數(shù)據(jù)源配置文件,取得根元素
               
          */
              
          private static void load(){
                  SAXReader saxReader 
          = new SAXReader();
                  //加載數(shù)據(jù)庫XML配置文件
                  InputStream in 
          = ClassUtils.getResourceAsStream(Constant.DB_CONFIG); 
                  try{
                      Document document 
          = saxReader.read(in); //得到Document對(duì)象
                      coreModel = document.getRootElement(); //得到根元素
                  }catch(Exception e){
                      System.out.println(
          "XML配置文件未加載成功,請(qǐng)檢查");
                      
          throw new RuntimeException(e);
                  }
              }
                 將load方法靜態(tài)初始化:
              static{
                  load();
              }
                 通過XPATH路徑得到對(duì)應(yīng)的元素:
              /**
               * 通過XPATH得到元素對(duì)象
               * 
          @param xPath XPATH路徑
               * 
          @return 獲得Element對(duì)象
               
          */
              
          public static Element getElement(String xPath){
                  
          return (Element)coreModel.selectSingleNode(xPath);
              }
                 再寫一個(gè)方法,讀取數(shù)據(jù)源配置信息,將之放入HashMap中:
              /**
               * 取得數(shù)據(jù)源配置信息放入HashMap中
               * 
          @param hashmap 存放取得的數(shù)據(jù)源鍵值對(duì)
               * 
          @return 返回存放信息的HashMap
               
          */
              
          public static HashMap<String,String> iterateXML(HashMap<String,String> hashmap){
                  
          try{
                      Element database 
          = getElement("//demo/database"); //得到database節(jié)點(diǎn)
                      List list = database.elements(); //得到database元素下的子元素集合
                      /*
                       * 循環(huán)遍歷集合中的每一個(gè)元素
                       * 將每一個(gè)元素的元素名和值作為鍵值對(duì)放入HashMap中
                       
          */
                      
          for(Object obj:list){
                          Element element 
          = (Element)obj;
                          
          //getName()是元素名,getText()是元素值
                          hashmap.put(element.getName(), element.getText());
                      }        
                  }
          catch(Exception e){
                      e.printStackTrace();
                  }
                  
          return hashmap;
              }
                 構(gòu)造函數(shù):
              /**
               * 構(gòu)造函數(shù)初始化
               
          */
              
          public DataBaseConnect(){
                  HashMap
          <String,String> hashmap = new HashMap<String,String>();
                  hashmap 
          = iterateXML(hashmap);//取得數(shù)據(jù)源配置信息
                  driver = hashmap.get(Constant.DRIVER);
                  url 
          = hashmap.get(Constant.URL);
                  username 
          = hashmap.get(Constant.USERNAME);
                  password 
          = hashmap.get(Constant.PASSWORD);
              }
                 創(chuàng)建數(shù)據(jù)庫連接及關(guān)閉等操作,此處省略,請(qǐng)查看源碼。
                 最后我們寫一個(gè)main方法來測試一下是否能夠連接數(shù)據(jù)庫:

              public static void main(String[] args){
                  DataBaseConnect db 
          = new DataBaseConnect();
                  Connection con 
          = db.getConnection();
                  
          try{
                      PreparedStatement psmt 
          = con.prepareStatement("select count(*) from help_keyword");
                      ResultSet rs 
          = psmt.executeQuery();
                      rs.next();
                      System.out.println(rs.getString(
          1));
                      rs.close();
                      psmt.close();
                      db.close(con);
                  }
          catch(Exception e){
                      
          throw new RuntimeException(e);
                  }
              }
                 如果沒問題,控制臺(tái)將打印出:381 的結(jié)果。
                 這里附上DBConnect.xml中SQL Server 2000和Oracle的配置,其中SQL Server采用JTDS驅(qū)動(dòng)。
          <?xml version="1.0" encoding="UTF-8"?>
          <demo>
              
          <database>
                  
          <driver>net.sourceforge.jtds.jdbc.Driver</driver>
                  
          <url>jdbc:jtds:sqlserver://127.0.0.1:1433/pubs</url>
                  
          <username>sa</username>
                  
          <password>自己密碼(無密碼就空著)</password>
              
          </database>
          </demo>

          <?xml version="1.0" encoding="UTF-8"?>
          <demo>
              
          <database>
                  
          <driver>oracle.jdbc.driver.OracleDriver</driver>
                  
          <url>jdbc:oracle:thin:@127.0.0.1:1521:自己的SID</url>
                  
          <username>system</username>
                  
          <password>自己密碼(無密碼就空著)</password>
              
          </database>
          </demo>
              本著對(duì)別人負(fù)責(zé),同時(shí)也是對(duì)自己負(fù)責(zé),全部代碼,大象都是親手寫出來在電腦上測試過,并且還模擬了產(chǎn)生異常的環(huán)境,請(qǐng)大家放心使用。
              點(diǎn)擊下載:dom4j-1.6.1.jar  jaxen-1.1-beta-7.jar  mysql-connector.jar  jtds.jar  classes12.jar
              點(diǎn)擊下載:demo  (直接導(dǎo)入即可,加入上面的jar包)
              本文為菠蘿大象原創(chuàng),如要轉(zhuǎn)載請(qǐng)注明出處。
          posted on 2008-08-09 22:24 菠蘿大象 閱讀(7101) 評(píng)論(8)  編輯  收藏 所屬分類: dom4j&jdom

          評(píng)論:
          # re: dom4j實(shí)戰(zhàn)(一)——使用dom4j從XML中讀取數(shù)據(jù)源配置 2008-08-18 10:49 | 昨夜流星
          頂一下,呵呵,正想學(xué)習(xí)DOM4J,希望樓主能繼續(xù)寫下去!  回復(fù)  更多評(píng)論
            
          # re: dom4j實(shí)戰(zhàn)(一)——使用dom4j從XML中讀取數(shù)據(jù)源配置 2009-01-04 16:59 | 王維娜
          支持,謝謝摟主  回復(fù)  更多評(píng)論
            
          # re: dom4j實(shí)戰(zhàn)(一)——使用dom4j從XML中讀取數(shù)據(jù)源配置 2010-05-24 21:32 | 大灰狼
          我把你的demo下載后,導(dǎo)入myeclipse中,運(yùn)行時(shí)出現(xiàn)如下的錯(cuò)誤提示:
          XML配置文件未加載成功,請(qǐng)檢查
          java.lang.ExceptionInInitializerError
          Caused by: java.lang.RuntimeException: org.dom4j.DocumentException: null Nested exception: null
          at com.demo.database.DataBaseConnect.load(DataBaseConnect.java:50)
          at com.demo.database.DataBaseConnect.<clinit>(DataBaseConnect.java:36)
          Caused by: org.dom4j.DocumentException: null Nested exception: null
          at org.dom4j.io.SAXReader.read(SAXReader.java:484)
          at org.dom4j.io.SAXReader.read(SAXReader.java:343)
          at com.demo.database.DataBaseConnect.load(DataBaseConnect.java:46)
          ... 1 more
          Exception in thread "main"
          我把文件路徑改為了tring DB_CONFIG = "/DBConnect.xml";如果是原來的tring DB_CONFIG = "DBConnect.xml";則不提示出錯(cuò),但是輸出的,url,username,password等全是NUll  回復(fù)  更多評(píng)論
            
          # re: dom4j實(shí)戰(zhàn)(一)——使用dom4j從XML中讀取數(shù)據(jù)源配置 2010-05-25 08:47 | 菠蘿大象
          @大灰狼
          你的這個(gè)問題應(yīng)該是把路徑設(shè)置錯(cuò)了,你如果沒改動(dòng)配置文件的位置,就不要改動(dòng)常量中設(shè)置的值,這兩者一定要對(duì)應(yīng),我的例子都測試過的,不然我也不敢放上來。  回復(fù)  更多評(píng)論
            
          # re: dom4j實(shí)戰(zhàn)(一)——使用dom4j從XML中讀取數(shù)據(jù)源配置 2010-05-25 10:49 | 大灰狼
          我是把你的demo全部導(dǎo)入的,jar包是有的dom4j-1.6.1.jar,導(dǎo)進(jìn)來直接運(yùn)行的時(shí)候輸出的url,username,password等全是NULL  回復(fù)  更多評(píng)論
            
          # re: dom4j實(shí)戰(zhàn)(一)——使用dom4j從XML中讀取數(shù)據(jù)源配置 2010-05-25 10:59 | 大灰狼
          發(fā)現(xiàn)DataBaseConnect()這個(gè)構(gòu)造函數(shù)沒有運(yùn)行  回復(fù)  更多評(píng)論
            
          # re: dom4j實(shí)戰(zhàn)(一)——使用dom4j從XML中讀取數(shù)據(jù)源配置 2010-05-25 11:14 | 大灰狼
          現(xiàn)在好了,謝謝菠蘿大象同志,原因是我沒有導(dǎo)入jaxen-1.1-beta-6.jar,加入這個(gè)一切順利  回復(fù)  更多評(píng)論
            
          # re: dom4j實(shí)戰(zhàn)(一)——使用dom4j從XML中讀取數(shù)據(jù)源配置 2010-05-25 21:48 | 菠蘿大象
          @大灰狼
          呵呵,恭喜你,自己調(diào)試成功,又積累了一次經(jīng)驗(yàn)。  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 新竹市| 景谷| 甘孜| 彰武县| 彭水| 东乌珠穆沁旗| 康马县| 阳原县| 台北县| 无极县| 自治县| 沧州市| 滦南县| 昌平区| 辉南县| 泾川县| 麦盖提县| 清水县| 翼城县| 曲水县| 靖远县| 察雅县| 许昌市| 泰兴市| 肇东市| 彩票| 酒泉市| 惠安县| 彭水| 温州市| 南郑县| 周宁县| 景泰县| 崇义县| 禄丰县| 曲阳县| 巴林左旗| 邵阳县| 白沙| 凤山市| 杨浦区|