中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > Java > J2SE
一个基本成熟的数据库连接池(part 1)<修正后>
作者:未知 时间:2005-07-24 21:13 出处:JR 责编:chinaitpower
              摘要:一个基本成熟的数据库连接池(part 1)<修正后>
最近,本人着手开发要有一个有强大后台的网站,在使用连接池时,觉得使用服务器自带的连接池总有些受限制。同时,为了加深对Java的学习和研究。写下了下面的连接池类。
该连接池主要有一下功能;

1)初始化一次,到处使用。
2)强大的日志功能,记录每一个sql动作,包括Connection、ResultSet 和Statement
3)根据连接的数量,定时自动回收已经释放或超时的连接。
4)配置灵活,可以使用各种JDBC驱动程序,支持多驱动程序。

更新说明:
1)新增了字符集配置项。
2) 新增了调试开关,便于使用前调试。
3)更改了日志日期输出格式。
4)排除了createStatement l里的一个bug (感谢rouselion的使用反馈)
5)修正了被封装类的getXXX函数的潜在的问题。

源代码:

  1. //file : *****< ConnectionManager.java >****
  2. /*
  3. *  @Title  连接池
  4. *  @Author: zxg
  5. *  @Version 2.5
  6. *  @Memo:定义数据库连接及其数据库连接池等
  7. */
  8. package com.dbaccess.dbpool;
  9. import java.io.*;
  10. import java.sql.*;
  11. import java.util.*;
  12. import com.mysql.jdbc.Driver;
  13. public class ConnectionManager {
  14.     static private ConnectionManager instance; // 唯一实例
  15. //    static private int clients;
  16.     static private long checkperiod=0;
  17.     private Vector drivers = new Vector();
  18.     private Hashtable pools = new Hashtable();
  19.     private Timer checkConnTimer=new Timer();
  20.     //调试模式开关
  21.     private static boolean debug=false;
  22.     
  23.     //字符集哈西表
  24.     static private Hashtable Characters= new Hashtable();
  25.     static private PrintWriter log;
  26.     /**
  27.     * 返回唯一实例.如果是第一次调用此方法,则创建实例
  28.     *
  29.     * @return ConnectionManager 唯一实例
  30.     */
  31.     static synchronized public ConnectionManager getInstance() {
  32.         if (instance == null) {
  33.             instance = new ConnectionManager();
  34.         }
  35. //        clients++;
  36.         return instance;
  37.     }
  38.     /**
  39.     * 建构函数私有以防止其它对象创建本类实例
  40.     */
  41.     private ConnectionManager() {
  42.         init();
  43.     }
  44.     /**
  45.     * 读取属性完成初始化
  46.     */
  47.     private void init() {
  48.         Properties    dbProps=null;
  49.         try {
  50.             InputStream    is =  getClass().getResourceAsStream("db.properties");
  51.             dbProps = new Properties();
  52.             dbProps.load(is);
  53.         }
  54.         catch (Exception e) {
  55.             e.printStackTrace();
  56.             System.err.println("不能读取属性文件= " +
  57.             "请确保db.properties在CLASSPATH指定的路径中");
  58.             return;
  59.         }
  60.         String logFile = dbProps.getProperty("logfile""log.txt");
  61.         String logPath=System.getProperty("user.dir");
  62.         if(!logPath.endsWith("/"))logPath=logPath+"/";
  63.         logFile=logPath+logFile;
  64.         if(debug){
  65.             System.out.println(logFile);
  66.             System.out.println("===============DEBUG====================");
  67.         }
  68.         try {
  69.             log = new PrintWriter(new FileWriter(logFile, true), true);
  70.         }
  71.         catch (IOException e) {
  72.             System.err.println("无法打开日志文件: " + logFile);
  73.             log = new PrintWriter(System.err);
  74.         }
  75.         String ckPeriod=dbProps.getProperty("checkperiod","5");
  76.         try {
  77.              checkperiod= Long.valueOf(ckPeriod).longValue()*60*1000;
  78.         }
  79.         catch (NumberFormatException e) {
  80.             log("错误的最大连接数限制: " + ckPeriod + "  连接池: ");
  81.             log("使用默认值 5 分钟");
  82.             checkperiod = 5*60*1000;
  83.         }
  84.         loadDrivers(dbProps);
  85.         createPools(dbProps);
  86.     }
  87.     /**
  88.     * 装载和注册所有JDBC驱动程序
  89.     *
  90.     * @param props 属性
  91.     */
  92.     private void loadDrivers(Properties props) {
  93.         String driverClasses = props.getProperty("drivers");
  94.         StringTokenizer st = new StringTokenizer(driverClasses);
  95.         while (st.hasMoreElements()) {
  96.             String driverClassName = st.nextToken().trim();
  97.             try {
  98.                 Driver driver = (Driver)Class.forName(driverClassName).newInstance();
  99.                 if(driver!=null){
  100.                     DriverManager.registerDriver(driver);
  101.                     drivers.addElement(driver);
  102.                     log("Begin");
  103.                     log("成功注册JDBC驱动程序" + driverClassName);
  104.                 }
  105.                 else{
  106.                     log("Begin");
  107.                     log("注册JDBC驱动程序" + driverClassName+"失败");
  108.                 }
  109.             }
  110.             catch (Exception e) {
  111.                 log("Begin");
  112.                 log("无法注册JDBC驱动程序: " + driverClassName + ", 错误: " + e);
  113.             }
  114.         }
  115.     }
  116.     /**
  117.     * 根据指定属性创建连接池实例.
  118.     *
  119.     * @param props 连接池属性
  120.     */
  121.     private void createPools(Properties props) {
  122.         Enumeration propNames = props.propertyNames();
  123.         while (propNames.hasMoreElements()) {
  124.             String name = (String) propNames.nextElement();
  125.             if (name.endsWith(".url")) {
  126.                 String poolName=name.substring(0,name.indexOf("."));
  127.                 //记录该连接池的字符集设置
  128.                 String character=props.getProperty(poolName+".character","gb2312");
  129.                 Characters.put(poolName,character);
  130.                 try{
  131.                     PoolInfoObject pio=new PoolInfoObject(poolName,props);
  132.                     ConnectionPool  pool = new ConnectionPool(pio);
  133.                     pools.put(poolName, pool);
  134.                     //1分钟后开始每隔checkperiod分钟检查一次连接池情况
  135.                     checkConnTimer.schedule(pool,60*1000,checkperiod);
  136.                     log("成功创建连接池" + poolName);
  137.                 }catch(Exception e){
  138.                     log(e,"创建DBConnectionPool出错");
  139.                 }
  140.             }
  141.         }
  142.     }
  143.     /**
  144.     * 将连接对象返回给由名字指定的连接池
  145.     *
  146.     * @param name 在属性文件中定义的连接池名字
  147.     * @param con 连接对象
  148.     */
  149.     public void freeConnection(String name, Connection conn) {
  150.         ConnectionPool pool = (ConnectionPool) pools.get(name);
  151.         if (pool != null) {
  152.             pool.freeConnection(conn);
  153.         }
  154.     }
  155.     /**
  156.     * 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数
  157.     * 限制,则创建并返回新连接
  158.     *
  159.     * @param name 在属性文件中定义的连接池名字
  160.     * @return Connection 可用连接或null
  161.     */
  162.     public Connection getConnection(String name) {
  163.         ConnectionPool pool = (ConnectionPool) pools.get(name);
  164.         if (pool != null) {
  165.             return pool.getConnection();
  166.         }
  167.         return null;
  168.     }
  169.     /**
  170.     * 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制,
  171.     * 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.
  172.     *
  173.     * @param name 连接池名字
  174.     * @param time 以毫秒计的等待时间
  175.     * @return Connection 可用连接或null
  176.     */
  177.     public Connection getConnection(String name, long time) {
  178.         ConnectionPool pool = (ConnectionPool) pools.get(name);
  179.         if (pool != null) {
  180.             return pool.getConnection(time);
  181.         }
  182.         return null;
  183.     }
  184.     /**
  185.     * 关闭所有连接,撤销驱动程序的注册
  186.     */
  187.     public synchronized void release() {
  188.     // 等待直到最后一个客户程序调用
  189. //        if (--clients != 0) {
  190. //            return;
  191. //        }
  192.         checkConnTimer.cancel();
  193.         Enumeration allPools = pools.elements();
  194.         while (allPools.hasMoreElements()) {
  195.             ConnectionPool pool = (ConnectionPool) allPools.nextElement();
  196.             pool.cancel();
  197.             pool.release();
  198.         }
  199.         Enumeration allDrivers = drivers.elements();
  200.         while (allDrivers.hasMoreElements()) {
  201.             Driver driver = (Driver) allDrivers.nextElement();
  202.             try {
  203.                 DriverManager.deregisterDriver(driver);
  204.                 log("撤销JDBC驱动程序 " + driver.getClass().getName()+"的注册");
  205.             }
  206.             catch (SQLException e) {
  207.                 log(e,"无法撤销下列JDBC驱动程序的注册: " + driver.getClass().getName());
  208.             }
  209.         }
  210.     }
  211.     /**
  212.      * 取字符集设置参数。
  213.      * @param poolName
  214.      * @return String
  215.     */
  216.     static public String getCharacter(String poolName) {
  217.         return (String)Characters.get(poolName);
  218.     }
  219.     /**
  220.     * 将文本信息写入日志文件
  221.     */
  222.     static public void log(String msg) {
  223.         if(debug==trueSystem.out.println( getLocalTime()+ " " + msg);
  224.         else log.println( getLocalTime()+ " " + msg);
  225.     }
  226.     /**
  227.     * 将文本信息与异常写入日志文件
  228.     */
  229.     static public void log(Throwable e, String msg) {
  230.         if(debug==true){
  231.             System.err.println( getLocalTime()+ " " + msg);
  232.             e.printStackTrace(log);
  233.         }else{
  234.             log.println(getLocalTime() + " " + msg);
  235.             e.printStackTrace(log);
  236.         }
  237.     }
  238.     /**
  239.      * 获取当前系统时间
  240.      * @return String
  241.      */
  242.     private static  String getLocalTime(){
  243.         int tt[];
  244.         String TT[];
  245.         tt= new int[6];
  246.         TT=new String[6];
  247.         Calendar cl=Calendar.getInstance();
  248.         tt[5]=cl.get(Calendar.SECOND);
  249.          tt[4]=cl.get(Calendar.MINUTE);
  250.           tt[3]=cl.get(Calendar.HOUR_OF_DAY);
  251.            tt[2]=cl.get(Calendar.DAY_OF_MONTH);
  252.         tt[1]=cl.get(Calendar.MONTH)+1;
  253.         tt[0]=cl.get(Calendar.YEAR);
  254.         for(int i=0;i<6 ;i++){
  255.             if(tt[i]<10)
  256.                 TT[i]="0"+Integer.toString(tt[i]);
  257.             else
  258.                 TT[i]=Integer.toString(tt[i]);
  259.         }
  260.         String t="";
  261.         //连接日期                        //连接时间
  262.         t+=TT[0]+"-"+TT[1]+"-"+TT[2]+" "+TT[3]+":"+TT[4]+":"+TT[5];
  263.         return t;
  264.     }
  265.     //test==========================================test
  266.     /**
  267.      * Method main
  268.      *
  269.      *
  270.      * @param args
  271.      *
  272.      */
  273.     public static void main(String[] args) {
  274.         ConnectionManager dcm=null;
  275.         try{
  276.             dcm=ConnectionManager.getInstance();
  277.             Connection conn=dcm.getConnection("mysql");
  278.             Connection conn1=dcm.getConnection("mysql");
  279.             Connection conn2=dcm.getConnection("mysql");
  280.             ResultSet rs;
  281.             System.out.println("start");
  282.             String sql="select * from user ";
  283.             System.out.println(":::::::::1");
  284.             Statement st=conn.createStatement();
  285.             if(st==null) {
  286.                 ConnectionManager.log("main--error while get \"Statement\"");
  287.                 return;            }
  288.             System.out.println("执行第"+1+"次检索");
  289.             rs=st.executeQuery(sql);
  290.             if(rs==null){
  291.                 ConnectionManager.log("main--error while get \"ResultSet\"");
  292.                 return;
  293.             }
  294.             System.out.println("\r\n");
  295.             while(rs.next()){
  296.                 System.out.println(rs.getString(1));
  297.                 System.out.println(rs.getString(2));
  298.                 System.out.println(rs.getString(3));
  299.                 System.out.println();
  300.             }
  301.             rs.close();
  302.             st.close();
  303.             //rs=null;
  304.             //st=null;
  305.             System.out.println(":::::::::2");
  306.             st = conn.createStatement();
  307.             System.out.println("执行第"+2+"次检索");
  308.             sql="select * from user";
  309.             rs=st.executeQuery(sql);
  310.             if(rs==null){
  311.                 ConnectionManager.log("main--error while get \"ResultSet\"");
  312.                 return;
  313.             }
  314.             while(rs.next()){
  315.                 System.out.println("TTT:::TTT");
  316.                 System.out.println(rs.getString(1));
  317.                 System.out.println(rs.getString(2));
  318.                 System.out.println(rs.getString(3));
  319.                 System.out.println();
  320.             }
  321.             rs.close();
  322.             st.close();
  323.             rs=null;
  324.             st=null;
  325.        dcm.freeConnection("mysql",conn);
  326.           
  327.             conn1.close();
  328.             conn2.close();
  329.             conn=null;
  330.             conn1=null;
  331.             conn2=null;
  332.             dcm.release();
  333.         }catch(SQLException e){
  334.             ConnectionManager.log(e,"main--error");
  335.         }
  336.     }
  337. }
  338. //===========================================================================//
  339. //file : *****< ConnectionPool.java >****
  340. /***************连接池类***********/
  341. /**
  342. * 此类定义了一个连接池.它能够根据要求创建新连接,直到预定的最
  343. * 大连接数为止.在返回连接给客户程序之前,它能够验证连接的有效性.
  344. * 它继承自 TimerTask 被 ConnectionManager 类的timer成员调度
  345. */
  346. package com.dbaccess.dbpool;
  347. import java.sql.*;
  348. import java.util.*;
  349. import java.util.Date;
  350. public class ConnectionPool extends TimerTask{
  351.     private int countConn;
  352.     private Vector freeConns = new Vector();
  353.     private Vector usingConns = new Vector();
  354.     private long maxUseTime;//使用中的连接最大空闲时间
  355.     private long maxFreeTime;//空闲的连接最大空闲时间(在连接数未小于最小连接数时,关闭此连接)
  356.     private long maxConn;//最大连接数
  357.     private long minConn;//最小连接数
  358.     private long OnlineFreeTime ;//最大在线时间
  359.     private long maxNoneOnlineTime;//无人在线最大保留时间
  360.     private String name;//连接池名(name)
  361.     private String url;
  362.     private String user;
  363.     private String password;
  364.     private String option;
  365.     /**
  366.     * 创建新的连接池
  367.     *
  368.     * @param pio 连接池信息
  369.     */
  370.     public ConnectionPool(PoolInfoObject pio) {
  371.         this.name = pio.poolName;
  372.         this.url = pio.url;
  373.         this.user = pio.user;
  374.         this.password = pio.password;
  375.         this.option=pio.optionConnection;
  376.         this.maxConn = pio.maxConnection;
  377.         this.minConn = pio.minConnection;
  378.         this.OnlineFreeTime = pio.maxOnlineFreeTime;
  379.         this.maxNoneOnlineTime = pio.maxNoneOnlineTime;
  380.         if(this.minConn<=0) this.minConn=10;
  381.         log("End One Part\r\n");
  382.         for(int i=0; i<minConn;i++){
  383.             newConnection();
  384.         }
  385.     }
  386.     /**
  387.     * 将新建的连接添加到连接池
  388.     *
  389.     * @param connobj 新建的连接
  390.     */
  391.     public synchronized void freeConnection(ConnectionObject connobj) {
  392.         // 将指定连接加入到向量末尾
  393.         try{
  394.             connobj.setInUse(false);
  395.             freeConns.addElement(connobj);
  396.             usingConns.removeElement(connobj);
  397.             log("成功记录一个新建连接或者回收一个已释放连接");
  398.             notifyAll();
  399.         }catch(ArrayIndexOutOfBoundsException e){
  400.             log(e,"freeConnection(ConnectionObject connobj) --失败");
  401.         }
  402.     }
  403.     /**
  404.     * 将不再使用的连接返回给连接池
  405.     *
  406.     * @param conn 客户程序主动释放的连接
  407.     */
  408.     public synchronized void freeConnection(Connection conn) {
  409.         // 将指定连接加入到向量末尾
  410.         ConnectionObject connobj=null;
  411.         int i;
  412.         for(i=0;i<usingConns.size();i++)
  413.         {
  414.             connobj=(ConnectionObject)usingConns.get(i);
  415.             if(connobj.getConnection(false)==conn)
  416.                 break;
  417.         }
  418.         if(i<usingConns.size()){
  419.             try{
  420.                 connobj.setInUse(false);
  421.                 freeConns.addElement(connobj);
  422.                 usingConns.removeElement(connobj);
  423.                 log("客户程序主动释放连接--成功回收一个连接");
  424.                 notifyAll();
  425.             }catch(Exception e){
  426.                 log(e,"客户程序主动释放连接--回收一个连接--失败");
  427.             }
  428.         }
  429.     }
  430.     /**
  431.     * 从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接
  432.     * 数限制,则创建新连接.如原来登记为可用的连接不再有效,则从向量删除之,
  433.     * 然后递归调用自己以尝试新的可用连接.
  434.     * @return Connection
  435.     */
  436.     public synchronized Connection getConnection() {
  437.         ConnectionObject connobj = null;
  438.         Connection conn=null;
  439.         // 获取向量中第一个可用连接
  440.         try {
  441.             connobj = (ConnectionObject) freeConns.get(0);
  442.         }
  443.         catch (Exception e) {
  444.             log("End One Part\r\n");
  445.             log("从连接池" + name+"获取一个连接失败");
  446.             if( maxConn == 0 || countConn < maxConn) {
  447.                 connobj = newConnection();
  448.                 conn=connobj.getConnection(true);
  449.             }
  450.         }
  451.         //如没有空闲的连接且当前连接数小于最大连接数限制,则创建新连接
  452.         if(connobj==null && ( maxConn == 0 || countConn < maxConn)) {
  453.             log("从连接池" + name+"获取一个连接失败");
  454.             log("End One Part\r\n");
  455.             connobj = newConnection();
  456.             conn=connobj.getConnection(true);
  457.         }else if(connobj!=null)
  458.         {
  459.             conn=connobj.getConnection(false);
  460.             if (conn==null) conn=connobj.getConnection(true);
  461.         }
  462.         if (conn != null) {
  463.             connobj.setLastAccessTime(new Date().getTime());
  464.             connobj.setInUse(true);
  465.             usingConns.addElement(connobj);
  466.             freeConns.removeElementAt(0);
  467.             return conn;
  468.         }else{
  469.             log("获取连接" + name+"失败--连接数量已达最大上限");
  470.             return null;
  471.         }
  472.     }
  473.     /**
  474.     * 从连接池获取可用连接.可以指定客户程序能够等待的最长时间
  475.     * 参见前一个getConnection()方法.
  476.     *
  477.     * @param timeout 以毫秒计的等待时间限制
  478.     */
  479.     public synchronized Connection getConnection(long timeout) {
  480.         long startTime = new Date().getTime();
  481.         Connection conn=null;
  482.         while ((conn = getConnection()) == null) {
  483.             try {
  484.                 wait(timeout);//??????????????
  485.             }
  486.             catch (InterruptedException e){
  487.             }
  488.             if ((new Date().getTime() - startTime) >= timeout) {
  489.                 // wait()返回的原因是超时?????????
  490.                 return null;
  491.             }
  492.         }
  493.         return conn;
  494.     }
  495.     /**
  496.     * 关闭所有连接
  497.     */
  498.     public synchronized void release() {
  499. //        cancel();
  500.         Enumeration allConnections = freeConns.elements();
  501.         while (allConnections.hasMoreElements()) {
  502.             ConnectionObject connobj = (ConnectionObject) allConnections.nextElement();
  503.             try {
  504.                 connobj.close();
  505.                 connobj=null;
  506.                 log("关闭连接池" + name+"中的一个连接");
  507.             }
  508.             catch (SQLException e) {//SQLException
  509.                 log(e, "无法关闭连接池" + name+"中的连接");
  510.             }
  511.         }
  512.         freeConns.removeAllElements();
  513.         //
  514.         allConnections = usingConns.elements();
  515.         while (allConnections.hasMoreElements()) {
  516.             ConnectionObject connobj = (ConnectionObject) allConnections.nextElement();
  517.             try {
  518.                 connobj.close();
  519.                 connobj=null;
  520.                 log("关闭连接池" + name+"中的一个连接");
  521.             }
  522.             catch (SQLException e) {//SQLException
  523.                 log(e, "无法关闭连接池" + name+"中的连接");
  524.             }
  525.         }
  526.         usingConns.removeAllElements();
  527.     }
  528.     /**
  529.     * 创建新的连接
  530.     */
  531.     private ConnectionObject newConnection() {
  532.         ConnectionObject connobj= null;
  533.         try {
  534.             log("连接池" + name+"创建一个新的连接对象");
  535.             String URL=url+option;
  536.              log("URL=" +URL );
  537.              Connection conn = DriverManager.getConnection(URL,user,password);
  538.             connobj=new ConnectionObject(conn,false);
  539.             connobj.setPoolName(name);
  540.             freeConnection(connobj);
  541.             countConn++;
  542.         }
  543.         catch (SQLException e) {
  544.             log(e, "无法创建下列URL的连接: " + url+" for User= " +user+" Password="+password);
  545.             return null;
  546.         }
  547.         return connobj;
  548.     }
  549.     //检查各连接状态(每checkperiod分钟一次)
  550.     
  551.     public synchronized void run (){
  552.         ConnectionObject connobj=null;
  553.         //是否在maxNoneOnlineTime长时间内没有任何连接被使用。
  554.         if(usingConns.size()==0 && (freeConns.size()==minConn || countConn==1)){
  555.             boolean bCanFree=true;
  556.             if(countConn==1)
  557.                 return;
  558.             else{
  559.                 for(int j=0;j<freeConns.size();j++){
  560.                     connobj=(ConnectionObject)freeConns.get(j);
  561.                     long lt=new Date().getTime()-connobj.getLastAccessTime();
  562.                     if(lt<maxNoneOnlineTime){
  563.                         bCanFree=false;
  564.                         break;
  565.                     }
  566.                 }
  567.             }
  568.             if(bCanFree){
  569.                 log("run--连接池里的连接太闲--现在关闭部分连接,保持一个连接 ");
  570.                 
  571.                 while(freeConns.size()>1){
  572.                     try{
  573.                         connobj=(ConnectionObject)freeConns.get(0);
  574.                         connobj.close();
  575.                         connobj=null;
  576.                         freeConns.removeElementAt(0);
  577.                         countConn--;
  578.                     }catch(SQLException e){
  579.                         log(e,"run--连接池的连接太闲--关闭部分连接,保持一个连接--失败");
  580.                     }
  581.                 }
  582.                 log("关闭连接数量"+Long.toString(minConn-1));
  583.             }
  584.             return;
  585.         }
  586.         //回收 正在使用中的已经"关闭"(释放)的连接 和 使用时间已经超时的连接
  587.         int i=0;
  588.         while(i<usingConns.size()){
  589.              connobj=(ConnectionObject)usingConns.get(i);
  590.             if(connobj.isInUse()==false){
  591.                 try{
  592.                         log("run--回收 正在使用中的已经\"关闭\"(释放)的连接");
  593.                         freeConnection(connobj);
  594.                         i--;
  595.                 }catch(ArrayIndexOutOfBoundsException e){
  596.                     log(e,"run--回收 正在使用中的已经\"关闭\"(释放)的连接--失败");
  597.                 }
  598.             }else{
  599.                 long nowtime=new Date().getTime();
  600.                 long t=nowtime-connobj.getLastAccessTime();
  601.                 try{
  602.                     if(t>OnlineFreeTime){//超时时间为OnlineFreeTime分钟
  603.                         log("run--回收 使用时间已经超时的连接");
  604.                         freeConnection(connobj);
  605.                         i--;
  606.                     }
  607.                 }catch(ArrayIndexOutOfBoundsException e ){
  608.                     log(e,"run--回收 使用时间已经超时的连接--失败");
  609.                 }
  610.             }
  611.             i++;
  612.         }
  613.         //删除 空闲的已经被意外关闭的连接
  614.         i=0;
  615.         while(i<freeConns.size()){
  616.             connobj= (ConnectionObject)freeConns.get(i);
  617.             try{
  618.                 if(connobj.isClosed()){
  619.                     connobj=null;
  620.                     freeConns.removeElementAt(i);
  621.                     countConn--;
  622.                     i--;
  623.                     log("run--删除 空闲的已经被意外关闭的连接");
  624.                 }
  625.             }catch(Exception e){
  626.                 log(e,"run--删除 空闲的已经被意外关闭的连接-失败");
  627.             }
  628.             i++;
  629.         }
  630.         //删除 从空闲连接中多余的(大于最小连接数的)连接
  631.         long cc=countConn-minConn;
  632.         i=0;
  633.         while(i<cc && freeConns.size()>1){
  634.             try{
  635.                 connobj=(ConnectionObject)freeConns.get(0);
  636.                 connobj.close();
  637.                 connobj=null;
  638.                 freeConns.removeElementAt(0);
  639.                 countConn--;
  640.                 log("run--删除 从空闲连接中多余的(大于最小连接数的)连接 ");
  641.             }catch(SQLException e){
  642.                 log(e,"run--从空闲连接中多余的(大于最小连接数的)连接--失败");
  643.             }
  644.             i++;
  645.         }
  646.         //增加连接 保持要求的最小连接数
  647.         if(cc<0){
  648.             cc=-cc;
  649.             log("End One Part\r\n");
  650.             log("run--增加连接 保持要求的最小连接数");
  651.             for(i=0;i<cc;i++){
  652.                 newConnection();
  653.             }
  654.         }
  655.         //增加连接 保持至少有一个可用连接
  656.         if(freeConns.size()<1){
  657.             log("End One Part\r\n");
  658.             log("run--增加连接 保持至少有一个可用连接");
  659.             newConnection();
  660.         }
  661.         log("run--once");
  662.     //    notifyAll();
  663.     }
  664.     /**
  665.     * 将文本信息写入日志文件
  666.     */
  667.     private void log(String msg) {
  668.         msg="POOLMSG:Name:["+name+"];Msg:"+msg;
  669.         ConnectionManager.log(msg);
  670.     }
  671.     /**
  672.     * 将文本信息与异常写入日志文件
  673.     */
  674.     private void log(Throwable e, String msg) {
  675.         msg="POOLERR:Name:["+name+"];Msg:"+msg;
  676.         ConnectionManager.log(e,msg);
  677.     }
  678. }
  679. //file : *****< PoolInfoObject .java >****
  680. /***************连接池信息类***********/
  681. package com.dbaccess.dbpool;
  682. import java.util.*;
  683. public class PoolInfoObject {
  684.     
  685.     public String poolName="";
  686.     
  687.     public String url="";
  688.     public String user="";
  689.     public String password="";
  690.     public String optionConnection="";//连接选项
  691.     
  692.     public long maxConnection=0;//最大连接数
  693.     public long minConnection=0;// 最小连接数
  694.     
  695.     public long maxOnlineFreeTime=0;//最大在线空闲时间
  696.     public long maxNoneOnlineTime=0;//最大无人在线时间。超过此时间后仅保持一个连接
  697.     
  698.     public PoolInfoObject(String poolName,Properties props) throws Exception
  699.     {
  700.         this.poolName=poolName;
  701.         
  702.         url = props.getProperty(poolName + ".url");
  703.         
  704.         if (url == null) {
  705.             log("没有为连接池" + poolName + "指定URL");
  706.             throw new Exception("没有为连接池" + poolName + "指定URL");
  707.         }
  708.         
  709.         this.user = props.getProperty(poolName + ".user");
  710.         this.password = props.getProperty(poolName + ".password");
  711.         this.optionConnection=props.getProperty(poolName+".option","");
  712.         
  713.         String maxconn = props.getProperty(poolName + ".maxconn""0");
  714.         String minconn = props.getProperty(poolName + ".minconn""10");
  715.         
  716.         String maxoft=props.getProperty(poolName + ".maxonlinefreetime""30");
  717.         String maxnot=props.getProperty(poolName + ".maxnoneonlinetime""180");
  718.         
  719.         try {
  720.             maxConnection = Long.valueOf(maxconn).longValue();
  721.             
  722.         }
  723.         catch (NumberFormatException e) {
  724.             log("错误的最大连接数限制: " + maxconn + "  连接池: " + poolName);
  725.             log("使用默认值 0(无限制)");
  726.             maxConnection = 0;
  727.         }
  728.         
  729.         try {
  730.             minConnection = Long.valueOf(minconn).longValue();
  731.             
  732.         }
  733.         catch (NumberFormatException e) {
  734.             log("错误的最小连接数限制: " + minconn + "  连接池: " + poolName);
  735.             log("使用默认值 10 个");
  736.             minConnection = 10;
  737.         }
  738.         
  739.         
  740.         try {
  741.             maxOnlineFreeTime =Long.valueOf(maxoft).longValue()*60*1000;
  742.             
  743.         }
  744.         
  745.         catch (NumberFormatException e) {
  746.             log("错误的最大在线空闲时间: " + maxoft + " 连接池: " + poolName);
  747.             log("使用默认值 30 分钟");
  748.             
  749.             maxOnlineFreeTime = 30*60*1000;
  750.         }
  751.         
  752.         try {
  753.             
  754.             maxNoneOnlineTime = Long.valueOf(maxnot).longValue()*60*1000;
  755.             
  756.         }
  757.         
  758.         catch (NumberFormatException e) {
  759.             log("错误的最大空闲时间:  " + maxnot + " 连接池: " + poolName);
  760.             log("使用默认值 1 小时");
  761.             maxNoneOnlineTime = 60*60*1000;
  762.         }
  763.         
  764.     }
  765.     /**
  766.     * 将文本信息写入日志文件
  767.     */
  768.     private void log(String msg) {
  769.         msg="POOLMSG:Name:["+poolName+"];Msg:"+msg;
  770.         ConnectionManager.log(msg);
  771.     }
  772.     
  773.     /**
  774.     * 将文本信息与异常写入日志文件
  775.     */
  776.     private void log(Throwable e, String msg) {
  777.         msg="POOLERR:Name:["+poolName+"];Msg:"+msg;
  778.         ConnectionManager.log(e,msg);
  779.     }
  780. }
  781. //file : *****< db.properties >****#pool info
  782. //典型的连接池配置文件
  783. #日志文件
  784. logfile=log.txt
  785. #检测连接的频率 单位:分钟次
  786. checkperiod=5
  787. #如果有多个驱动可以以“:”分开如drivers=com.mysql.jdbc.Driver:com.oracle.jdbc.Driver
  788. drivers=com.mysql.jdbc.Driver
  789. #指明你的数据库所使用的字符集(新添项)
  790. mysql.character=gb2312
  791. mysql.url=jdbc:mysql://localhost:3306/test?
  792. mysql.option=useUnicode=true&&characterEncoding=GB2312&autoReconnect=true
  793. mysql.user=zxg
  794. mysql.password=333444
  795. #连接池数量限制
  796. mysql.maxconn=0
  797. mysql.minconn=10
  798. #超时参数 单位:分钟
  799. #最大在线空闲时间
  800. mysql.maxonlinefreetime=30
  801. #最大无人在线时间
  802. mysql.maxnoneonlinetime=60


       [Part 2]    

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有