ITPub博客

首页 > 应用开发 > Java > Java数据库连接池(经典)

Java数据库连接池(经典)

Java 作者:liujian_jed 时间:2018-01-29 18:36:08 0 删除 编辑

转载自:http://langzixin.iteye.com/blog/808975

不错的案例,收藏起来,要不时间长了就找不到了

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

1、创建web项目(MyEclipse)

 

 2、web服务器使用Tomcat(XP环境),测试数据库使用oracle(XP环境),mysql(Ubuntu环境)

 

 3、将上面的java代码引入web项目的src中

 

 4、引入oracle、mysql的jdbc驱动

 

 5、 在src下创建文件db.properties,内容如下(注意后缀名是properties)

 

 

 其中oracle测试数据库、oracle用户名、oracle密码、root密码根据自己情况填写

6、jsp代码
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
  2. <%@ page import="java.sql.*"%>  
  3. <%@ page import="myDB.DBConnectionManager"%>  
  4. <%  
  5. String path = request.getContextPath();  
  6. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
  7. %>  
  8.   
  9. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  10. <html>  
  11.     <head>  
  12.         <base href="<%=basePath%>">  
  13.   
  14.         <title>My JSP 'index.jsp' starting page</title>  
  15.         <meta http-equiv="pragma" content="no-cache">  
  16.         <meta http-equiv="cache-control" content="no-cache">  
  17.         <meta http-equiv="expires" content="0">  
  18.         <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  19.         <meta http-equiv="description" content="This is my page">  
  20.         <!--  
  21.     <link rel="stylesheet" type="text/css" href="styles.css">  
  22.     -->  
  23.     </head>  
  24.   
  25.     <body>  
  26.         This is my JSP page.  
  27.         <br>  
  28. <%  
  29. try  
  30.  {  
  31.   DBConnectionManager dbM = DBConnectionManager.getInstance(); //单例模式,只是在第一次调用该方法时生成实例,在服务器中该类只保存一个实例  
  32.   out.println("JAVA连接池类测试<br/>");  
  33.   Connection con = dbM.getConnection("mysqldb");//mysqldb是db.properties配置文件中设置的  
  34.   out.print(dbM.getClient());  
  35.   if (con == null)  
  36.   {  
  37.    out.println("不能获取数据库连接.");  
  38.    //dbM.release();  
  39.   }  
  40.   else  
  41.   {  
  42.    Statement stmt = con.createStatement();  
  43.    ResultSet rs = stmt.executeQuery("select * from first_table");  
  44.    while (rs.next())  
  45.    {  
  46.     out.print(rs.getString(1));  
  47.     out.print("<br/>");  
  48.    }  
  49.    rs.close();  
  50.    stmt.close();  
  51.    dbM.freeConnection("mysqldb", con);  
  52.      
  53.   }  
  54.     
  55.   Connection oraclecon = dbM.getConnection("oracledb");//oracledb是db.properties配置文件中设置的  
  56.   out.print(dbM.getClient());  
  57.   if (oraclecon == null)  
  58.   {  
  59.    out.println("不能获取数据库连接.");  
  60.    //dbM.release();  
  61.   }  
  62.   else  
  63.   {  
  64.    Statement stmt = oraclecon.createStatement();  
  65.    ResultSet rs = stmt.executeQuery("select * from on_campus_student where rownum<=5");  
  66.    while (rs.next())  
  67.    {  
  68.     out.print(rs.getString(1));  
  69.     out.print("<br/>");  
  70.    }  
  71.    rs.close();  
  72.    stmt.close();  
  73.    dbM.freeConnection("oracledb", oraclecon);  
  74.      
  75.   }  
  76.  } catch (Exception ee)  
  77.  {  
  78.   out.print(ee.getMessage());  
  79.  }  
  80. %>  
  81.     </body>  
  82. </html>  

 7、可以方便的获得各种数据库连接(预先在db.properties中配置) 

 

 com.mysql.jdbc.Driver oracle.jdbc.driver.OracleDriver

 

 不同数据库之间用空格隔开即可


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/672726/viewspace-2150622/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-12-30

  • 博文量
    27
  • 访问量
    33758