论坛首页 Java企业应用论坛

javaBean数据库连接池

浏览 5530 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (1) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-10-08  
实现简单的数据库连接池:
java 代码
  1. /**     
  2.  *  @author  zhupan(温柔一刀) Creation date: 06-10-2006    
  3.  */     
  4. package com.zhupan.StrutsArticle.Utils;      
  5.      
  6. import java.sql.Connection;      
  7.      
  8. public class DBConnection {      
  9.     public static synchronized Connection getConnection() throws Exception {      
  10.         Connection conn = null;      
  11.         DBConnectionManager dbc;      
  12.         try {      
  13.             dbc = DBConnectionManager.getInstance();      
  14.             conn = dbc.getConnection(" idb ");      
  15.         } catch (Exception e) {      
  16.         }      
  17.         return conn;      
  18.     }      
  19.      
  20. }      
java 代码
  1. /**   
  2.  *  @author  zhupan(温柔一刀)  Creation date: 05-01-2006  
  3.  */  
  4. package com.zhupan.StrutsArticle.Utils;   
  5.   
  6. import java.io.FileWriter;   
  7. import java.io.IOException;   
  8. import java.io.InputStream;   
  9. import java.io.PrintWriter;   
  10. import java.sql.Connection;   
  11. import java.sql.Driver;   
  12. import java.sql.DriverManager;   
  13. import java.sql.SQLException;   
  14. import java.util.Date;   
  15. import java.util.Enumeration;   
  16. import java.util.Hashtable;   
  17. import java.util.Properties;   
  18. import java.util.StringTokenizer;   
  19. import java.util.Vector;   
  20.   
  21. /** */  
  22. /**  
  23.  * 连接池 管理类DBConnectionManager支持对一个或多个由属性文件定义的数据库连接  
  24.  * 池的访问.客户程序可以调用getInstance()方法访问本类的唯一实例.  
  25.  */  
  26. public class DBConnectionManager {   
  27.     static private DBConnectionManager instance; // 唯一实例   
  28.   
  29.     static private int clients;   
  30.   
  31.     private Vector drivers = new Vector();   
  32.   
  33.     private PrintWriter log;   
  34.   
  35.     private Hashtable pools = new Hashtable();   
  36.   
  37.     /** */  
  38.     /**  
  39.      * 返回唯一实例.如果是第一次调用此方法,则创建实例  
  40.      *   
  41.      * @return DBConnectionManager 唯一实例  
  42.      */  
  43.     static synchronized public DBConnectionManager getInstance() {   
  44.         if (instance == null) {   
  45.             instance = new DBConnectionManager();   
  46.         }   
  47.         clients++;   
  48.         return instance;   
  49.     }   
  50.   
  51.     /** */  
  52.     /**  
  53.      * 建构函数私有以防止其它对象创建本类实例  
  54.      */  
  55.     private DBConnectionManager() {   
  56.         init();   
  57.     }   
  58.   
  59.     /** */  
  60.     /**  
  61.      * 将连接对象返回给由名字指定的连接池  
  62.      *   
  63.      * @param name  
  64.      *            在属性文件中定义的连接池名字  
  65.      * @param con  
  66.      *            连接对象  
  67.      */  
  68.     public void freeConnection(String name, Connection con) {   
  69.         DBConnectionPool pool = (DBConnectionPool) pools.get(name);   
  70.         if (pool != null) {   
  71.             pool.freeConnection(con);   
  72.         }   
  73.     }   
  74.   
  75.     /** */  
  76.     /**  
  77.      * 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数 限制,则创建并返回新连接  
  78.      *   
  79.      * @param name  
  80.      *            在属性文件中定义的连接池名字  
  81.      * @return Connection 可用连接或null  
  82.      */  
  83.     public Connection getConnection(String name) {   
  84.         DBConnectionPool pool = (DBConnectionPool) pools.get(name);   
  85.         if (pool != null) {   
  86.             return pool.getConnection();   
  87.         }   
  88.         return null;   
  89.     }   
  90.   
  91.     /** */  
  92.     /**  
  93.      * 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制, 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.  
  94.      *   
  95.      * @param name  
  96.      *            连接池名字  
  97.      * @param time  
  98.      *            以毫秒计的等待时间  
  99.      * @return Connection 可用连接或null  
  100.      */  
  101.     public Connection getConnection(String name, long time) {   
  102.         DBConnectionPool pool = (DBConnectionPool) pools.get(name);   
  103.         if (pool != null) {   
  104.             return pool.getConnection(time);   
  105.         }   
  106.         return null;   
  107.     }   
  108.   
  109.     /** */  
  110.     /**  
  111.      * 关闭所有连接,撤销驱动程序的注册  
  112.      */  
  113.     public synchronized void release() {   
  114.         // 等待直到最后一个客户程序调用   
  115.         if (--clients != 0) {   
  116.             return;   
  117.         }   
  118.   
  119.         Enumeration allPools = pools.elements();   
  120.         while (allPools.hasMoreElements()) {   
  121.             DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();   
  122.             pool.release();   
  123.         }   
  124.         Enumeration allDrivers = drivers.elements();   
  125.         while (allDrivers.hasMoreElements()) {   
  126.             Driver driver = (Driver) allDrivers.nextElement();   
  127.             try {   
  128.                 DriverManager.deregisterDriver(driver);   
  129.                 log(" 撤销JDBC驱动程序  " + driver.getClass().getName() + " 的注册 ");   
  130.             } catch (SQLException e) {   
  131.                 log(e, " 无法撤销下列JDBC驱动程序的注册:  " + driver.getClass().getName());   
  132.             }   
  133.         }   
  134.     }   
  135.   
  136.     /** */  
  137.     /**  
  138.      * 根据指定属性创建连接池实例.  
  139.      *   
  140.      * @param props  
  141.      *            连接池属性(温柔一刀)  
  142.      */  
  143.     private void createPools(Properties props) {   
  144.         Enumeration propNames = props.propertyNames();   
  145.         while (propNames.hasMoreElements()) {   
  146.             String name = (String) propNames.nextElement();   
  147.             if (name.endsWith(" .url ")) {   
  148.                 String poolName = name.substring(0, name.lastIndexOf(" . "));   
  149.                 String url = props.getProperty(poolName + " .url ");   
  150.                 if (url == null) {   
  151.                     log(" 没有为连接池 " + poolName + " 指定URL ");   
  152.                     continue;   
  153.                 }   
  154.                 String user = props.getProperty(poolName + " .user ");   
  155.                 String password = props.getProperty(poolName + " .password ");   
  156.                 String maxconn = props.getProperty(poolName + " .maxconn ",   
  157.                         " 0 ");   
  158.                 int max;   
  159.                 try {   
  160.                     max = Integer.valueOf(maxconn).intValue();   
  161.                 } catch (NumberFormatException e) {   
  162.                     log(" 错误的最大连接数限制:  " + maxconn + "  .连接池:  " + poolName);   
  163.                     max = 0;   
  164.                 }   
  165.                 DBConnectionPool pool = new DBConnectionPool(poolName, url,   
  166.                         user, password, max);   
  167.                 pools.put(poolName, pool);   
  168.                 log(" 成功创建连接池 " + poolName);   
  169.             }   
  170.         }   
  171.     }   
  172.   
  173.     /** */  
  174.     /**  
  175.      * 读取属性完成初始化(温柔一刀)  
  176.      */  
  177.     private void init() {   
  178.         InputStream is = getClass().getResourceAsStream(" db.properties ");   
  179.         Properties dbProps = new Properties();   
  180.         try {   
  181.             dbProps.load(is);   
  182.         } catch (Exception e) {   
  183.             System.err.println(" 不能读取属性文件.  "  
  184.                     + " 请确保db.properties在CLASSPATH指定的路径中 ");   
  185.             return;   
  186.         }   
  187.         String logFile = dbProps.getProperty(" logfile ",   
  188.                 " DBConnectionManager.log ");   
  189.         try {   
  190.             log = new PrintWriter(new FileWriter(logFile, true), true);   
  191.         } catch (IOException e) {   
  192.             System.err.println(" 无法打开日志文件:  " + logFile);   
  193.             log = new PrintWriter(System.err);   
  194.         }   
  195.         loadDrivers(dbProps);   
  196.         createPools(dbProps);   
  197.     }   
  198.   
  199.     /** */  
  200.     /**  
  201.      * 装载和注册所有JDBC驱动程序(温柔一刀)  
  202.      *   
  203.      * @param props  
  204.      *            属性  
  205.      */  
  206.     private void loadDrivers(Properties props) {   
  207.         String driverClasses = props.getProperty(" drivers ");   
  208.         StringTokenizer st = new StringTokenizer(driverClasses);   
  209.         while (st.hasMoreElements()) {   
  210.             String driverClassName = st.nextToken().trim();   
  211.             try {   
  212.                 Driver driver = (Driver) Class.forName(driverClassName)   
  213.                         .newInstance();   
  214.                 DriverManager.registerDriver(driver);   
  215.                 drivers.addElement(driver);   
  216.                 log(" 成功注册JDBC驱动程序 " + driverClassName);   
  217.             } catch (Exception e) {   
  218.                 log(" 无法注册JDBC驱动程序:  " + driverClassName + " , 错误:  " + e);   
  219.             }   
  220.         }   
  221.     }   
  222.   
  223.     /** */  
  224.     /**  
  225.      * 将文本信息写入日志文件(温柔一刀)  
  226.      */  
  227.     private void log(String msg) {   
  228.         log.println(new Date() + " :  " + msg);   
  229.     }   
  230.   
  231.     /** */  
  232.     /**  
  233.      * 将文本信息与异常写入日志文件(温柔一刀)  
  234.      */  
  235.     private void log(Throwable e, String msg) {   
  236.         log.println(new Date() + " :  " + msg);   
  237.         e.printStackTrace(log);   
  238.     }   
  239.   
  240.     /** */  
  241.     /**  
  242.      * 此内部类定义了一个连接池.它能够根据要求创建新连接,直到预定的最 大连接数为止.在返回连接给客户程序之前,它能够验证连接的有效性.(温柔一刀)  
  243.      */  
  244.     class DBConnectionPool {   
  245.         private int checkedOut;   
  246.   
  247.         private Vector freeConnections = new Vector();   
  248.   
  249.         private int maxConn;   
  250.   
  251.         private String name;   
  252.   
  253.         private String password;   
  254.   
  255.         private String URL;   
  256.   
  257.         private String user;   
  258.   
  259.         /** */  
  260.         /**  
  261.          * 创建新的连接池  
  262.          *   
  263.          * @param name  
  264.          *            连接池名字  
  265.          * @param URL  
  266.          *            数据库的JDBC URL  
  267.          * @param user  
  268.          *            数据库帐号,或 null  
  269.          * @param password  
  270.          *            密码,或 null(温柔一刀)  
  271.          * @param maxConn  
  272.          *            此连接池允许建立的最大连接数  
  273.          */  
  274.         public DBConnectionPool(String name, String URL, String user,   
  275.                 String password, int maxConn) {   
  276.             this.name = name;   
  277.             this.URL = URL;   
  278.             this.user = user;   
  279.             this.password = password;   
  280.             this.maxConn = maxConn;   
  281.         }   
  282.   
  283.         /** */  
  284.         /**  
  285.          * 将不再使用的连接返回给连接池(温柔一刀)  
  286.          *   
  287.          * @param con  
  288.          *            客户程序释放的连接  
  289.          */  
  290.         public synchronized void freeConnection(Connection con) {   
  291.             // 将指定连接加入到向量末尾   
  292.             freeConnections.addElement(con);   
  293.             checkedOut--;   
  294.             notifyAll();   
  295.         }   
  296.   
  297.         /** */  
  298.         /**  
  299.          * 从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接 数限制,则创建新连接.如原来登记为可用的连接不再有效,则从向量删除之,  
  300.          * 然后递归调用自己以尝试新的可用连接.(温柔一刀)  
  301.          */  
  302.         public synchronized Connection getConnection() {   
  303.             Connection con = null;   
  304.             if (freeConnections.size() > 0) {   
  305.                 // 获取向量中第一个可用连接   
  306.                 con = (Connection) freeConnections.firstElement();   
  307.                 freeConnections.removeElementAt(0);   
  308.                 try {   
  309.                     if (con.isClosed()) {   
  310.                         log(" 从连接池 " + name + " 删除一个无效连接 ");   
  311.                         // 递归调用自己,尝试再次获取可用连接   
  312.                         con = getConnection();   
  313.                     }   
  314.                 } catch (SQLException e) {   
  315.                     log(" 从连接池 " + name + " 删除一个无效连接 ");   
  316.                     // 递归调用自己,尝试再次获取可用连接   
  317.                     con = getConnection();   
  318.                 }   
  319.             } else if (maxConn == 0 || checkedOut < maxConn) {   
  320.                 con = newConnection();   
  321.             }   
  322.             if (con != null) {   
  323.                 checkedOut++;   
  324.             }   
  325.             return con;   
  326.         }   
  327.   
  328.         /** */  
  329.         /**  
  330.          * 从连接池获取可用连接.可以指定客户程序能够等待的最长时间 参见前一个getConnection()方法.  
  331.          *   
  332.          * @param timeout  
  333.          *            以毫秒计的等待时间限制  
  334.          */  
  335.         public synchronized Connection getConnection(long timeout) {   
  336.             long startTime = new Date().getTime();   
  337.             Connection con;   
  338.             while ((con = getConnection()) == null) {   
  339.                 try {   
  340.                     wait(timeout);   
  341.                 } catch (InterruptedException e) {   
  342.                 }   
  343.                 if ((new Date().getTime() - startTime) >= timeout) {   
  344.                     // wait()返回的原因是超时   
  345.                     return null;   
  346.                 }   
  347.             }   
  348.             return con;   
  349.         }   
  350.   
  351.         /** */  
  352.         /**  
  353.          * 关闭所有连接(温柔一刀)  
  354.          */  
  355.         public synchronized void release() {   
  356.             Enumeration allConnections = freeConnections.elements();   
  357.             while (allConnections.hasMoreElements()) {   
  358.                 Connection con = (Connection) allConnections.nextElement();   
  359.                 try {   
  360.                     con.close();   
  361.                     log(" 关闭连接池 " + name + " 中的一个连接 ");   
  362.                 } catch (SQLException e) {   
  363.                     log(e, " 无法关闭连接池 " + name + " 中的连接 ");   
  364.                 }   
  365.             }   
  366.             freeConnections.removeAllElements();   
  367.         }   
  368.   
  369.         /** */
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics