重构JDBC数据库连接池

Pool抽象类

package com.sy.day2.t4;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public abstract class Pool {
    public String propertiesName = "db.properties";
    private static Pool instance = null; //定义唯一实例
    protected  int maxConnect = 100; //最大链接数
    protected int normalConnect; //保持连接数
    protected String driverName = null; //驱动字符串
    protected Driver driver = null; //驱动变量
    //私有构造函数,不允许外界访问
    protected Pool() {
        try {
            init();
            loadDrivers(driverName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //初始化所有从配置文件读取的成员变量
    private void init() throws IOException {
        InputStream is = Pool.class.getResourceAsStream(propertiesName);
        Properties p = new Properties();
        p.load(is);
        this.driverName = p.getProperty("db.driver");
        this.maxConnect = Integer.parseInt(p.getProperty("db.maxConnect"));
        this.normalConnect = Integer.parseInt(p.getProperty("db.normalConnect"));
    }
    //装载和注册所有JDBC驱动
    protected void loadDrivers(String dri){
        String driverClassName = dri;
        try {
            driver = (Driver) Class.forName(driverClassName).newInstance();
            DriverManager.registerDriver(driver);
            System.out.println("成功注册"+driverClassName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //创建连接池
    public abstract void createPool();
    /**
     * (单例模式)返回数据库连接池 Pool的实例
     * @Param driverName 数据库驱动字符串
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static synchronized Pool getInstance() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        if(instance != null){
            instance = (Pool) Class.forName("com.sy.day2.t4.Pool").newInstance();
        }
        return instance;
    }
    //获得一个可用的连接,如果没有就创建一个连接,且小于最大连接限制
    public abstract Connection getConnection();

    //获得一个可用连接,有时间限制
    public abstract Connection getConnection(long time);

    //将连接对象返回连接池
    public abstract void freeConnection(Connection connection);

    //返回当前空闲连接数
    public abstract int getNum();

    //返回当前工作的链接数
    public abstract int getNumActive();

    protected synchronized void release(){
        //撤销驱动
        try {
            DriverManager.deregisterDriver(driver);
            System.out.println("撤销JDBC驱动程序"+driver.getClass().getName());
        } catch (SQLException sqlException) {
            System.out.println("无法撤销JDBC驱动程序注册:"+driver.getClass().getName());
            sqlException.printStackTrace();
        }
    }
}

DBConnection类数据库连接池

package com.sy.day2.t4;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;

public final class DBConnectionPool extends Pool{
    private int checkedOut; //正在使用的链接数
    private Vector<Connection> freeConnections = new Vector<>(); //存放产生的连接对象容器
    private String passWord = null; //密码
    private String url = null; //连接路径
    private String userName = null; //用户名
    private static int num = 0; //空闲链接数
    private static int numActive = 0; //当前可用连接数
    private static DBConnectionPool pool = null; //连接池实例变量

    protected DBConnectionPool() {
        try {
            init();
            for (int i = 0; i < normalConnect; i++) { //初始normalConn个连接
                Connection c = newConnection();
                if(c!=null){
                    freeConnections.addElement(c);
                    num++;
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    //初始化
    private void init() throws IOException {
        InputStream is = DBConnectionPool.class.getResourceAsStream(propertiesName);
        Properties p = new Properties();
        p.load(is);
        this.userName = p.getProperty("db.user");
        this.passWord = p.getProperty("db.pwd");
        this.driverName = p.getProperty("db.driver");
        this.url = p.getProperty("db.url");
        this.maxConnect = Integer.parseInt(p.getProperty("db.maxConnect"));
        this.normalConnect = Integer.parseInt(p.getProperty("db.normalConnect"));
    }

    private Connection newConnection() {
        Connection con = null;
        try {
            if(userName == null) con= DriverManager.getConnection(url);
            else con=DriverManager.getConnection(url,userName,passWord);
            System.out.println("连接池创建一个新的连接");
        } catch (SQLException sqlException) {
            System.out.println("无法创建一个url连接"+url);
            sqlException.printStackTrace();
            return null;
        }
        return con;
    }
    //产生数据连接池
    public static synchronized DBConnectionPool getInstance(){
        if(pool==null) pool=new DBConnectionPool();
        return pool;
    }
    @Override
    public void createPool() {

    }
    //(单例模式)获取一个可用连接
    @Override
    public Connection getConnection() {
        Connection con = null;
        if(freeConnections.size()>0){ //还有空闲连接
            num--;
            con = (Connection) freeConnections.firstElement();
            freeConnections.removeElementAt(0);
            try {
                if(con.isClosed()){
                    System.out.println("从连接池中删除一个无效连接");
                    con = getConnection();
                }
            } catch (SQLException sqlException) {
                System.out.println("从连接池中删除一个无效连接");
                sqlException.printStackTrace();
            }
        }else if(maxConnect == 0|| checkedOut<maxConnect){  //没有空闲连接且当前连接小于
                                                            //最大允许值,最大值为0时,不加限制
            con = newConnection();
        }
        if(con!=null){
            //当前连接数+1
            checkedOut++;
        }
        numActive++;
        return con;
    }
    //获取一个连接,并加上等待时间限制(单位为毫秒),超时返回null
    @Override
    public Connection getConnection(long timeOut) {
        long startTime = new Date().getTime();
        Connection con = null;
        while ((con = getConnection())==null){
            try {
                wait(timeOut);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if((new Date().getTime()-startTime) >= timeOut) return null; //超时
        }
        return con;
    }
    public synchronized  void release(){
        try {
            //将连接赋值到美剧中
            Enumeration allConnections = freeConnections.elements();
            //使用循环关闭所有连接
            while (allConnections.hasMoreElements()){
                Connection con = (Connection) allConnections.nextElement();
                try {
                    con.close();
                    num--;
                } catch (SQLException sqlException) {
                    System.out.println("无法关闭连接池中的连接");
                    sqlException.printStackTrace();
                }
            }
            freeConnections.removeAllElements();
            numActive = 0;
        }finally {
            super.release();
        }
    }
    @Override
    public synchronized void freeConnection(Connection connection) {
        freeConnections.add(connection);
        num++;
        checkedOut--;
        numActive--;
        notifyAll();//解锁
    }

    @Override
    public int getNum() {
        return num;
    }

    @Override
    public int getNumActive() {
        return numActive;
    }
}

 

posted @ 2021-01-18 10:07  relo  阅读(96)  评论(0)    收藏  举报