gembin

          OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

          HBase, Hadoop, ZooKeeper, Cassandra

          Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

          There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

          About Me

           

          一個(gè)經(jīng)試用效果非常不錯(cuò)的數(shù)據(jù)庫(kù)連接池

          一個(gè)經(jīng)試用效果非常不錯(cuò)的數(shù)據(jù)庫(kù)連接池
           

          前言:

              雖說(shuō)現(xiàn)在許多企業(yè)級(jí)的應(yīng)用服務(wù)器均自己帶有數(shù)據(jù)庫(kù)連接池功能,就連 Tomcat 也支持了這種功能。然而在許多時(shí)候,我們還是要使用數(shù)據(jù)庫(kù)連接池,如:訪問(wèn)數(shù)據(jù)庫(kù)的 Java 桌面應(yīng)用程序等。這個(gè)數(shù)據(jù)庫(kù)連接池是我根據(jù)《 Inside Servlets 》一書中的示例改寫而成,經(jīng)過(guò)試用,效果非常不錯(cuò)。特發(fā)布共享。

           

           源代碼

           

          //ConnectionPool.java 
          
          package com.abner.dbconnector; 
          
          import java.sql.*; 
          
          import java.util.*; 
          
          /** 
          
          * ConnectionPool 類創(chuàng)建了一個(gè)對(duì)特定數(shù)據(jù)庫(kù)指定大小的連接池。連接池對(duì)象 
          
          * 允許客戶端指定 JDBC 驅(qū)動(dòng)程序,數(shù)據(jù)庫(kù),使用數(shù)據(jù)庫(kù)的用戶名和密碼。而且, 
          
          * 客戶端能指定連接池的在初始創(chuàng)建是產(chǎn)生數(shù)據(jù)庫(kù)連接的數(shù)量,和指定當(dāng)連接 
          
          * 不夠時(shí)每次自動(dòng)增加連接的數(shù)量及連接池最多的數(shù)據(jù)庫(kù)連接的數(shù)量。 
          
          * 
          
          * 對(duì)外提供的方法有: ConnectionPool :構(gòu)造函數(shù) 
          
          * getInitialConnections: 返回連接池初始化大小 
          
          * setInitialConnections: 設(shè)置連接池初始化大小 
          
          * getIncrementalConnections: 返回連接池自動(dòng)增加的增量 
          
          * setIncrementalConnections: 設(shè)置連接池自動(dòng)增加的大小 
          
          * getMaxConnections :獲得連接池的最大可允許的連接數(shù) 
          
          * setMaxConnections :設(shè)置連接池的最大可允許的連接數(shù) 
          
          * getTestTable :獲得測(cè)試表的名字 
          
          * setTestTable :設(shè)置測(cè)試表的名字 
          
          * createPool: 創(chuàng)建連接池 , 線程己同步 
          
          * getConnection: 從連接池中獲得一個(gè)數(shù)據(jù)庫(kù)連接 
          
          * returnConnection: 返回一個(gè)連接到連接池中 
          
          * refreshConnections: 刷新連接池 
          
          * closeConnectionPool: 關(guān)閉連接池 
          
          * 
          
          * 
          
          * @author abnerchai Email: josserchai@yahoo.com 
          
          * @version 1.0.0 
          
          * 
          
          */ 
          
          public class ConnectionPool { 
          
             private String jdbcDriver = ""; // 數(shù)據(jù)庫(kù)驅(qū)動(dòng) 
          
             private String dbUrl = ""; // 數(shù)據(jù) URL 
          
             private String dbUsername = ""; // 數(shù)據(jù)庫(kù)用戶名 
          
             private String dbPassword = ""; // 數(shù)據(jù)庫(kù)用戶密碼 
          
             private String testTable = ""; // 測(cè)試連接是否可用的測(cè)試表名,默認(rèn)沒(méi)有測(cè)試表 
          
             private int initialConnections = 10; // 連接池的初始大小 
          
             private int incrementalConnections = 5;// 連接池自動(dòng)增加的大小 
          
             private int maxConnections = 50; // 連接池最大的大小 
          
             private Vector connections = null; // 存放連接池中數(shù)據(jù)庫(kù)連接的向量 , 初始時(shí)為 null 
          
          // 它中存放的對(duì)象為 PooledConnection 型 
          
          /** 
          
          * 構(gòu)造函數(shù) 
          
          * 
          
          * @param jdbcDriver String JDBC 驅(qū)動(dòng)類串 
          
          * @param dbUrl String 數(shù)據(jù)庫(kù) URL 
          
          * @param dbUsername String 連接數(shù)據(jù)庫(kù)用戶名 
          
          * @param dbPassword String 連接數(shù)據(jù)庫(kù)用戶的密碼 
          
          * 
          
          */ 
          
          public ConnectionPool(String jdbcDriver,String dbUrl,String dbUsername,String dbPassword) { 
          
             this.jdbcDriver = jdbcDriver; 
          
             this.dbUrl = dbUrl; 
          
             this.dbUsername = dbUsername; 
          
             this.dbPassword = dbPassword; 
          
          } 
          
          /** 
          
          * 返回連接池的初始大小 
          
          * 
          
          * @return 初始連接池中可獲得的連接數(shù)量 
          
          */ 
          
          public int getInitialConnections() { 
          
             return this.initialConnections; 
          
          } 
          
          /** 
          
          * 設(shè)置連接池的初始大小 
          
          * 
          
          * @param 用于設(shè)置初始連接池中連接的數(shù)量 
          
          */ 
          
          public void setInitialConnections(int initialConnections) { 
          
             this.initialConnections = initialConnections; 
          
          } 
          
          /** 
          
          * 返回連接池自動(dòng)增加的大小 、 
          
          * 
          
          * @return 連接池自動(dòng)增加的大小 
          
          */ 
          
          public int getIncrementalConnections() { 
          
             return this.incrementalConnections; 
          
          } 
          
          /** 
          
          * 設(shè)置連接池自動(dòng)增加的大小 
          
          * @param 連接池自動(dòng)增加的大小 
          
          */ 
          
          public void setIncrementalConnections(int incrementalConnections) { 
          
             this.incrementalConnections = incrementalConnections; 
          
          } 
          
          /** 
          
          * 返回連接池中最大的可用連接數(shù)量 
          
          * @return 連接池中最大的可用連接數(shù)量 
          
          */ 
          
          public int getMaxConnections() { 
          
             return this.maxConnections; 
          
          } 
          
          /** 
          
          * 設(shè)置連接池中最大可用的連接數(shù)量 
          
          * 
          
          * @param 設(shè)置連接池中最大可用的連接數(shù)量值 
          
          */ 
          
          public void setMaxConnections(int maxConnections) { 
          
             this.maxConnections = maxConnections; 
          
          } 
          
          /** 
          
          * 獲取測(cè)試數(shù)據(jù)庫(kù)表的名字 
          
          * 
          
          * @return 測(cè)試數(shù)據(jù)庫(kù)表的名字 
          
          */ 
          
          public String getTestTable() { 
          
             return this.testTable; 
          
          } 
          
          /** 
          
          * 設(shè)置測(cè)試表的名字 
          
          * @param testTable String 測(cè)試表的名字 
          
          */ 
          
          public void setTestTable(String testTable) { 
          
             this.testTable = testTable; 
          
          } 
          
          /** 
          
          * 
          
          * 創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)連接池,連接池中的可用連接的數(shù)量采用類成員 
          
          * initialConnections 中設(shè)置的值 
          
          */ 
          
          public synchronized void createPool() throws Exception { 
          
          // 確保連接池沒(méi)有創(chuàng)建 
          
          // 如果連接池己經(jīng)創(chuàng)建了,保存連接的向量 connections 不會(huì)為空 
          
          if (connections != null) { 
          
              return; // 如果己經(jīng)創(chuàng)建,則返回 
          
          } 
          
          // 實(shí)例化 JDBC Driver 中指定的驅(qū)動(dòng)類實(shí)例 
          
          Driver driver = (Driver) (Class.forName(this.jdbcDriver).newInstance()); 
          
          DriverManager.registerDriver(driver); // 注冊(cè) JDBC 驅(qū)動(dòng)程序 
          
          // 創(chuàng)建保存連接的向量 , 初始時(shí)有 0 個(gè)元素 
          
          connections = new Vector(); 
          
          // 根據(jù) initialConnections 中設(shè)置的值,創(chuàng)建連接。 
          
          createConnections(this.initialConnections); 
          
              System.out.println(" 數(shù)據(jù)庫(kù)連接池創(chuàng)建成功! "); 
          
          } 
          
          /** 
          
          * 創(chuàng)建由 numConnections 指定數(shù)目的數(shù)據(jù)庫(kù)連接 , 并把這些連接 
          
          * 放入 connections 向量中 
          
          * 
          
          * @param numConnections 要?jiǎng)?chuàng)建的數(shù)據(jù)庫(kù)連接的數(shù)目 
          
          */ 
          
          private void createConnections(int numConnections) throws SQLException { 
          
          // 循環(huán)創(chuàng)建指定數(shù)目的數(shù)據(jù)庫(kù)連接 
          
          for (int x = 0; x < numConnections; x++) { 
          
          // 是否連接池中的數(shù)據(jù)庫(kù)連接的數(shù)量己經(jīng)達(dá)到最大?最大值由類成員 maxConnections 
          
          // 指出,如果 maxConnections 為 0 或負(fù)數(shù),表示連接數(shù)量沒(méi)有限制。 
          
          // 如果連接數(shù)己經(jīng)達(dá)到最大,即退出。 
          
             if (this.maxConnections > 0 && this.connections.size() >= this.maxConnections) { 
          
                break; 
          
             } 
          
          //add a new PooledConnection object to connections vector 
          
          // 增加一個(gè)連接到連接池中(向量 connections 中) 
          
          try{ 
          
              connections.addElement(new PooledConnection(newConnection())); 
          
          }catch(SQLException e){ 
          
              System.out.println(" 創(chuàng)建數(shù)據(jù)庫(kù)連接失敗! "+e.getMessage()); 
          
              throw new SQLException(); 
          
          } 
          
              System.out.println(" 數(shù)據(jù)庫(kù)連接己創(chuàng)建 ......"); 
          
          } 
          
          } 
          
          /** 
          
          * 創(chuàng)建一個(gè)新的數(shù)據(jù)庫(kù)連接并返回它 
          
          * 
          
          * @return 返回一個(gè)新創(chuàng)建的數(shù)據(jù)庫(kù)連接 
          
          */ 
          
          private Connection newConnection() throws SQLException { 
          
          // 創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)連接 
          
          Connection conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword); 
          
          // 如果這是第一次創(chuàng)建數(shù)據(jù)庫(kù)連接,即檢查數(shù)據(jù)庫(kù),獲得此數(shù)據(jù)庫(kù)允許支持的 
          
          // 最大客戶連接數(shù)目 
          
          //connections.size()==0 表示目前沒(méi)有連接己被創(chuàng)建 
          
          if (connections.size() == 0) { 
          
             DatabaseMetaData metaData = conn.getMetaData(); 
          
             int driverMaxConnections = metaData.getMaxConnections(); 
          
          // 數(shù)據(jù)庫(kù)返回的 driverMaxConnections 若為 0 ,表示此數(shù)據(jù)庫(kù)沒(méi)有最大 
          
          // 連接限制,或數(shù)據(jù)庫(kù)的最大連接限制不知道 
          
          //driverMaxConnections 為返回的一個(gè)整數(shù),表示此數(shù)據(jù)庫(kù)允許客戶連接的數(shù)目 
          
          // 如果連接池中設(shè)置的最大連接數(shù)量大于數(shù)據(jù)庫(kù)允許的連接數(shù)目 , 則置連接池的最大 
          
          // 連接數(shù)目為數(shù)據(jù)庫(kù)允許的最大數(shù)目 
          
              if (driverMaxConnections > 0 && this.maxConnections > driverMaxConnections) { 
          
                this.maxConnections = driverMaxConnections; 
          
              } 
          
          } 
          
          return conn; // 返回創(chuàng)建的新的數(shù)據(jù)庫(kù)連接 
          
          } 
          
          /** 
          
          * 通過(guò)調(diào)用 getFreeConnection() 函數(shù)返回一個(gè)可用的數(shù)據(jù)庫(kù)連接 , 
          
          * 如果當(dāng)前沒(méi)有可用的數(shù)據(jù)庫(kù)連接,并且更多的數(shù)據(jù)庫(kù)連接不能創(chuàng) 
          
          * 建(如連接池大小的限制),此函數(shù)等待一會(huì)再嘗試獲取。 
          
          * 
          
          * @return 返回一個(gè)可用的數(shù)據(jù)庫(kù)連接對(duì)象 
          
          */ 
          
          public synchronized Connection getConnection() throws SQLException { 
          
          // 確保連接池己被創(chuàng)建 
          
          if (connections == null) { 
          
              return null; // 連接池還沒(méi)創(chuàng)建,則返回 null 
          
          } 
          
          Connection conn = getFreeConnection(); // 獲得一個(gè)可用的數(shù)據(jù)庫(kù)連接 
          
          // 如果目前沒(méi)有可以使用的連接,即所有的連接都在使用中 
          
          while (conn == null){ 
          
          // 等一會(huì)再試 
          
              wait(250); 
          
              conn = getFreeConnection(); // 重新再試,直到獲得可用的連接,如果 
          
          //getFreeConnection() 返回的為 null 
          
          // 則表明創(chuàng)建一批連接后也不可獲得可用連接 
          
          } 
          
          return conn;// 返回獲得的可用的連接 
          
          } 
          
          /** 
          
          * 本函數(shù)從連接池向量 connections 中返回一個(gè)可用的的數(shù)據(jù)庫(kù)連接,如果 
          
          * 當(dāng)前沒(méi)有可用的數(shù)據(jù)庫(kù)連接,本函數(shù)則根據(jù) incrementalConnections 設(shè)置 
          
          * 的值創(chuàng)建幾個(gè)數(shù)據(jù)庫(kù)連接,并放入連接池中。 
          
          * 如果創(chuàng)建后,所有的連接仍都在使用中,則返回 null 
          
          * @return 返回一個(gè)可用的數(shù)據(jù)庫(kù)連接 
          
          */ 
          
          private Connection getFreeConnection() throws SQLException { 
          
          // 從連接池中獲得一個(gè)可用的數(shù)據(jù)庫(kù)連接 
          
          Connection conn = findFreeConnection(); 
          
          if (conn == null) { 
          
          // 如果目前連接池中沒(méi)有可用的連接 
          
          // 創(chuàng)建一些連接 
          
          createConnections(incrementalConnections); 
          
          // 重新從池中查找是否有可用連接 
          
          conn = findFreeConnection(); 
          
          if (conn == null) { 
          
          // 如果創(chuàng)建連接后仍獲得不到可用的連接,則返回 null 
          
             return null; 
          
          } 
          
          } 
          
          return conn; 
          
          } 
          
          /** 
          
          * 查找連接池中所有的連接,查找一個(gè)可用的數(shù)據(jù)庫(kù)連接, 
          
          * 如果沒(méi)有可用的連接,返回 null 
          
          * 
          
          * @return 返回一個(gè)可用的數(shù)據(jù)庫(kù)連接 
          
          */ 
          
          private Connection findFreeConnection() throws SQLException { 
          
          Connection conn = null; 
          
          PooledConnection pConn = null; 
          
          // 獲得連接池向量中所有的對(duì)象 
          
          Enumeration en = connections.elements(); 
          
          // 遍歷所有的對(duì)象,看是否有可用的連接 
          
          while (en.hasMoreElements()) { 
          
             pConn = (PooledConnection) en.nextElement(); 
          
             if (!pConn.isBusy()) { 
          
              // 如果此對(duì)象不忙,則獲得它的數(shù)據(jù)庫(kù)連接并把它設(shè)為忙 
          
              conn = pConn.getConnection(); 
          
              pConn.setBusy(true); 
          
              // 測(cè)試此連接是否可用 
          
              if (!testConnection(conn)) { 
          
               // 如果此連接不可再用了,則創(chuàng)建一個(gè)新的連接, 
          
               // 并替換此不可用的連接對(duì)象,如果創(chuàng)建失敗,返回 null 
          
               try{ 
          
                 conn = newConnection(); 
          
               }catch(SQLException e){ 
          
                 System.out.println(" 創(chuàng)建數(shù)據(jù)庫(kù)連接失敗! "+e.getMessage()); 
          
                 return null; 
          
               } 
          
                pConn.setConnection(conn); 
          
             } 
          
             break; // 己經(jīng)找到一個(gè)可用的連接,退出 
          
          } 
          
          } 
          
          return conn;// 返回找到到的可用連接 
          
          } 
          
          /** 
          
          * 測(cè)試一個(gè)連接是否可用,如果不可用,關(guān)掉它并返回 false 
          
          * 否則可用返回 true 
          
          * 
          
          * @param conn 需要測(cè)試的數(shù)據(jù)庫(kù)連接 
          
          * @return 返回 true 表示此連接可用, false 表示不可用 
          
          */ 
          
          private boolean testConnection(Connection conn) { 
          
          try { 
          
             // 判斷測(cè)試表是否存在 
          
             if (testTable.equals("")) { 
          
               // 如果測(cè)試表為空,試著使用此連接的 setAutoCommit() 方法 
          
               // 來(lái)判斷連接否可用(此方法只在部分?jǐn)?shù)據(jù)庫(kù)可用,如果不可用 , 
          
               // 拋出異常)。注意:使用測(cè)試表的方法更可靠 
          
               conn.setAutoCommit(true); 
          
             } else {// 有測(cè)試表的時(shí)候使用測(cè)試表測(cè)試 
          
               //check if this connection is valid 
          
               Statement stmt = conn.createStatement(); 
          
               stmt.execute("select count(*) from " + testTable); 
          
          } 
          
          } catch (SQLException e) { 
          
          // 上面拋出異常,此連接己不可用,關(guān)閉它,并返回 false; 
          
          closeConnection(conn); 
          
          return false; 
          
          } 
          
          // 連接可用,返回 true 
          
          return true; 
          
          } 
          
          /** 
          
          * 此函數(shù)返回一個(gè)數(shù)據(jù)庫(kù)連接到連接池中,并把此連接置為空閑。 
          
          * 所有使用連接池獲得的數(shù)據(jù)庫(kù)連接均應(yīng)在不使用此連接時(shí)返回它。 
          
          * 
          
          * @param 需返回到連接池中的連接對(duì)象 
          
          */ 
          
          public void returnConnection(Connection conn) { 
          
          // 確保連接池存在,如果連接沒(méi)有創(chuàng)建(不存在),直接返回 
          
          if (connections == null) { 
          
          System.out.println(" 連接池不存在,無(wú)法返回此連接到連接池中 !"); 
          
          return; 
          
          } 
          
          PooledConnection pConn = null; 
          
          Enumeration en = connections.elements(); 
          
          // 遍歷連接池中的所有連接,找到這個(gè)要返回的連接對(duì)象 
          
          while (en.hasMoreElements()) { 
          
          pConn = (PooledConnection) en.nextElement(); 
          
          // 先找到連接池中的要返回的連接對(duì)象 
          
          if (conn == pConn.getConnection()) { 
          
          // 找到了 , 設(shè)置此連接為空閑狀態(tài) 
          
          pConn.setBusy(false); 
          
          break; 
          
          } 
          
          } 
          
          } 
          
          /** 
          
          * 刷新連接池中所有的連接對(duì)象 
          
          * 
          
          */ 
          
          public synchronized void refreshConnections() throws SQLException { 
          
          // 確保連接池己創(chuàng)新存在 
          
          if (connections == null) { 
          
          System.out.println(" 連接池不存在,無(wú)法刷新 !"); 
          
          return; 
          
          } 
          
          PooledConnection pConn = null; 
          
          Enumeration en = connections.elements(); 
          
          while (en.hasMoreElements()) { 
          
          // 獲得一個(gè)連接對(duì)象 
          
          pConn = (PooledConnection) en.nextElement(); 
          
          // 如果對(duì)象忙則等 5 秒 ,5 秒后直接刷新 
          
          if (pConn.isBusy()) { 
          
          wait(5000); // 等 5 秒 
          
          } 
          
          // 關(guān)閉此連接,用一個(gè)新的連接代替它。 
          
          closeConnection(pConn.getConnection()); 
          
          pConn.setConnection(newConnection()); 
          
          pConn.setBusy(false); 
          
          } 
          
          } 
          
          /** 
          
          * 關(guān)閉連接池中所有的連接,并清空連接池。 
          
          */ 
          
          public synchronized void closeConnectionPool() throws SQLException { 
          
          // 確保連接池存在,如果不存在,返回 
          
          if (connections == null) { 
          
             System.out.println(" 連接池不存在,無(wú)法關(guān)閉 !"); 
          
             return; 
          
          } 
          
          PooledConnection pConn = null; 
          
          Enumeration en = connections.elements(); 
          
          while (en.hasMoreElements()) { 
          
             pConn = (PooledConnection) en.nextElement(); 
          
          // 如果忙,等 5 秒 
          
             if (pConn.isBusy()) { 
          
                wait(5000); // 等 5 秒 
          
              } 
          
          //5 秒后直接關(guān)閉它 
          
          closeConnection(pConn.getConnection()); 
          
          // 從連接池向量中刪除它 
          
          connections.removeElement(pConn); 
          
          } 
          
          // 置連接池為空 
          
          connections = null; 
          
          } 
          
          /** 
          
          * 關(guān)閉一個(gè)數(shù)據(jù)庫(kù)連接 
          
          * 
          
          * @param 需要關(guān)閉的數(shù)據(jù)庫(kù)連接 
          
          */ 
          
          private void closeConnection(Connection conn) { 
          
          try { 
          
          conn.close(); 
          
          }catch (SQLException e) { 
          
          System.out.println(" 關(guān)閉數(shù)據(jù)庫(kù)連接出錯(cuò): "+e.getMessage()); 
          
          } 
          
          } 
          
          /** 
          
          * 使程序等待給定的毫秒數(shù) 
          
          * 
          
          * @param 給定的毫秒數(shù) 
          
          */ 
          
          private void wait(int mSeconds) { 
          
          try { 
          
          Thread.sleep(mSeconds); 
          
          } catch (InterruptedException e) { 
          
          } 
          
          } 
          
          /** 
          
          * 
          
          * 內(nèi)部使用的用于保存連接池中連接對(duì)象的類 
          
          * 此類中有兩個(gè)成員,一個(gè)是數(shù)據(jù)庫(kù)的連接,另一個(gè)是指示此連接是否 
          
          * 正在使用的標(biāo)志。 
          
          */ 
          
          class PooledConnection { 
          
             Connection connection = null;// 數(shù)據(jù)庫(kù)連接 
          
             boolean busy = false; // 此連接是否正在使用的標(biāo)志,默認(rèn)沒(méi)有正在使用 
          
             // 構(gòu)造函數(shù),根據(jù)一個(gè) Connection 構(gòu)告一個(gè) PooledConnection 對(duì)象 
          
             public PooledConnection(Connection connection) { 
          
               this.connection = connection; 
          
              } 
          
              // 返回此對(duì)象中的連接 
          
              public Connection getConnection() { 
          
                return connection; 
          
              } 
          
          // 設(shè)置此對(duì)象的,連接 
          
          public void setConnection(Connection connection) { 
          
             this.connection = connection; 
          
          } 
          
          // 獲得對(duì)象連接是否忙 
          
          public boolean isBusy() { 
          
             return busy; 
          
          } 
          
          // 設(shè)置對(duì)象的連接正在忙 
          
          public void setBusy(boolean busy) { 
          
             this.busy = busy; 
          
          } 
          
          } 
          
          } 
          
          這個(gè)程序所有的解釋我都詳細(xì)地寫在了源程序中,我想就不必多解說(shuō)了吧。

          如果你有改進(jìn)或修改,請(qǐng)保留原作者的聲明

          posted on 2007-09-21 10:47 gembin 閱讀(2973) 評(píng)論(1)  編輯  收藏

          評(píng)論

          # re: 一個(gè)經(jīng)試用效果非常不錯(cuò)的數(shù)據(jù)庫(kù)連接池 2007-09-22 00:15 千里冰封

          真的?哪天用用看  回復(fù)  更多評(píng)論   


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


          網(wǎng)站導(dǎo)航:
           

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(6)

          隨筆分類(440)

          隨筆檔案(378)

          文章檔案(6)

          新聞檔案(1)

          相冊(cè)

          收藏夾(9)

          Adobe

          Android

          AS3

          Blog-Links

          Build

          Design Pattern

          Eclipse

          Favorite Links

          Flickr

          Game Dev

          HBase

          Identity Management

          IT resources

          JEE

          Language

          OpenID

          OSGi

          SOA

          Version Control

          最新隨筆

          搜索

          積分與排名

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          free counters
          主站蜘蛛池模板: 罗田县| 桂平市| 泉州市| 玛纳斯县| 肃北| 华容县| 固始县| 固安县| 桃园县| 漳州市| 浠水县| 蓬溪县| 米林县| 克山县| 新沂市| 普安县| 安塞县| 凤山市| 双江| 泽普县| 昭觉县| 弥勒县| 海丰县| 洪湖市| 洪雅县| 慈利县| 黑山县| 西贡区| 舞钢市| 镇江市| 华蓥市| 南昌县| 谢通门县| 舞阳县| 牙克石市| 泸定县| 酒泉市| 青阳县| 浦东新区| 湛江市| 河源市|