• 数据库连接池及数据库连接获取(程序员的成长之路---第4篇)


    闲话少说,直接列举问题:

    ①AB两台数据库服务器做集群,由于两台服务器配置不一样,如何在代码中要实现每访问服务器A的数据库2次,才能访问服务器B的数据库1次。

    ②AB两台数据库服务器做读写分离,如何在代码中控制,查询数据使用服务器A的数据库连接,增删改使用服务器B的数据库连接。

    代码结构:

    代码实现:

    ①数据库连接信息默认值

    package com.keji10.core.jdbc.properties;
    
    /**
     * 类描述: 数据库连接信息默认值
     * 
     * @since 1.5
     * @version 1.0
     * @author xuanly
     * 
     */
    public interface JdbcPropertiesContants {
    
        /**
         * jdbc.maxActive最大活跃数(默认值)
         */
        public static final int JDBC_MAXACTIVE_DEFAULT = 20;
        /**
         * jdbc.maxIdle最大连接数(默认值)
         */
        public static final int JDBC_MAXIDLE_DEFAULT = 20;
        /**
         * jdbc.maxWait默认等待时间(默认值)
         */
        public static final int JDBC_MAXWAIT_DEFAULT = 10000;
        /**
         * jdbc.weight默认数据库连接池权重(默认值)
         */
        public static final int JDBC_WEIGHT_DEFAULT = 1;
    }

    package com.keji10.core.jdbc.properties;
    
    /**
     * 类描述: 数据库配置文件实体类
     * 
     * @since 1.5
     * @version 1.0
     * @author xuanly
     * 
     */
    public class JdbcPropertiesBean implements JdbcPropertiesContants {
        private String jdbcDriver;
        private String jdbcUrl;
        private String jdbcUserName;
        private String jdbcPassword;
        private int jdbcMaxactive;
        private int jdbcMaxidle;
        private int jdbcMaxwait;
        private int jdbcWeight;
    
        public String getJdbcDriver() {
            return jdbcDriver;
        }
    
        public void setJdbcDriver(String jdbcDriver) {
            this.jdbcDriver = jdbcDriver;
        }
    
        public String getJdbcUrl() {
            return jdbcUrl;
        }
    
        public void setJdbcUrl(String jdbcUrl) {
            this.jdbcUrl = jdbcUrl;
        }
    
        public String getJdbcUserName() {
            return jdbcUserName;
        }
    
        public void setJdbcUserName(String jdbcUserName) {
            this.jdbcUserName = jdbcUserName;
        }
    
        public String getJdbcPassword() {
            return jdbcPassword;
        }
    
        public void setJdbcPassword(String jdbcPassword) {
            this.jdbcPassword = jdbcPassword;
        }
    
        public int getJdbcWeight() {
            if (jdbcWeight == 0) {
                // 返回默认值
                return JDBC_WEIGHT_DEFAULT;
            }
            return jdbcWeight;
        }
    
        public void setJdbcWeight(int jdbcWeight) {
            this.jdbcWeight = jdbcWeight;
        }
    
        public int getJdbcMaxactive() {
            if (jdbcMaxactive == 0) {
                // 返回默认值
                return JDBC_MAXACTIVE_DEFAULT;
            }
            return jdbcMaxactive;
        }
    
        public void setJdbcMaxactive(int jdbcMaxactive) {
            this.jdbcMaxactive = jdbcMaxactive;
        }
    
        public int getJdbcMaxidle() {
            if (jdbcMaxidle == 0) {
                // 返回默认值
                return JDBC_MAXIDLE_DEFAULT;
            }
            return jdbcMaxidle;
        }
    
        public void setJdbcMaxidle(int jdbcMaxidle) {
            this.jdbcMaxidle = jdbcMaxidle;
        }
    
        public int getJdbcMaxwait() {
            if (jdbcMaxwait == 0) {
                // 返回默认值
                return JDBC_MAXWAIT_DEFAULT;
            }
            return jdbcMaxwait;
        }
    
        public void setJdbcMaxwait(int jdbcMaxwait) {
            this.jdbcMaxwait = jdbcMaxwait;
        }
    
        public String toString() {
            StringBuffer s = new StringBuffer();
            s.append("jdbcDriver    =" + jdbcDriver);
            s.append("jdbcUrl       =" + jdbcUrl);
            s.append("jdbcUserName  =" + jdbcUserName);
            s.append("jdbcPassword  =" + jdbcPassword);
            s.append("jdbcMaxactive =" + jdbcMaxactive);
            s.append("jdbcMaxidle   =" + jdbcMaxidle);
            s.append("jdbcMaxwait   =" + jdbcMaxwait);
            s.append("jdbcWeight    =" + jdbcWeight);
            return s.toString();
        }
    }

     ③数据库配置文件信息获取

    package com.keji10.core.jdbc.properties;
    
    import java.util.ResourceBundle;
    
    import org.apache.log4j.Logger;
    
    import com.keji10.core.exception.DBException;
    
    /**
     * 类描述: 数据库配置文件信息获取
     * 
     * @since 1.5
     * @version 1.0
     * @author xuanly
     * 
     */
    public class JdbcPropertiesManager {
        private Logger logger = Logger.getLogger(JdbcPropertiesManager.class.getName());
        // 单例模式Begin
        private static JdbcPropertiesManager instance = new JdbcPropertiesManager();
    
        private JdbcPropertiesManager() {
        }
    
        public static JdbcPropertiesManager getInstance() {
            return instance;
        }
    
        // 单例模式End
        private JdbcPropertiesBean jdbcPropertiesBean;
    
        /**
         * 获取jdbc.propertiesBean配置文件
         * 
         * @return JdbcPropertiesBean
         * @throws DBException
         */
        public JdbcPropertiesBean getJdbcPropertiesBean() throws DBException {
            return getJdbcPropertiesBean("jdbc");
        }
    
        public JdbcPropertiesBean getJdbcPropertiesBean(String propertieFile) throws DBException {
            ResourceBundle rb = ResourceBundle.getBundle(propertieFile);
            jdbcPropertiesBean = new JdbcPropertiesBean();
            try {
                jdbcPropertiesBean.setJdbcDriver(rb.getString("jdbc.driver"));
                jdbcPropertiesBean.setJdbcUrl(rb.getString("jdbc.url"));
                jdbcPropertiesBean.setJdbcUserName(rb.getString("jdbc.username"));
                jdbcPropertiesBean.setJdbcPassword(rb.getString("jdbc.password"));
            } catch (Exception e) {
                logger.warn("获取数据库连接配置文件【jdbc.driver】失败,执行无法启动!");
                logger.warn("获取数据库连接配置文件【jdbc.url】失败,执行无法启动!");
                logger.warn("获取数据库连接配置文件【jdbc.username】失败,执行无法启动!");
                logger.warn("获取数据库连接配置文件【jdbc.password】失败,执行无法启动!");
                logger.error(e);
                throw new DBException(e);
            }
            try {
                jdbcPropertiesBean.setJdbcMaxactive(Integer.valueOf(rb.getString("jdbc.maxActive")));
                jdbcPropertiesBean.setJdbcMaxidle(Integer.valueOf(rb.getString("jdbc.maxIdle")));
                jdbcPropertiesBean.setJdbcMaxwait(Integer.valueOf(rb.getString("jdbc.maxWait")));
                jdbcPropertiesBean.setJdbcWeight(Integer.valueOf(rb.getString("jdbc.weight")));
            } catch (Exception e) {
                logger.warn("获取数据库连接配置文件【jdbc.maxActive】失败,系统将执行默认配置");
                logger.warn("获取数据库连接配置文件【jdbc.maxIdle】失败,系统将执行默认配置");
                logger.warn("获取数据库连接配置文件【jdbc.maxWait】失败,系统将执行默认配置");
                logger.warn("获取数据库连接配置文件【jdbc.weight】失败,系统将执行默认配置");
            }
            return jdbcPropertiesBean;
        }
    
    }

    ④数据库连接池管理

    package com.keji10.core.jdbc.dataSource;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.sql.DataSource;
    
    import org.apache.commons.dbcp.BasicDataSource;
    import org.apache.log4j.Logger;
    
    import com.keji10.core.commons.ConfigBean;
    import com.keji10.core.exception.DBException;
    import com.keji10.core.jdbc.properties.JdbcPropertiesBean;
    import com.keji10.core.jdbc.properties.JdbcPropertiesManager;
    
    /**
     * 类描述:数据库连接池管理
     * 
     * @since 1.5
     * @version 1.0
     * @author chenairu
     * 
     */
    public class DBDataSource {
        private Logger logger = Logger.getLogger(DBDataSource.class.getName());
        // 单例模式begin
        private static DBDataSource instance = new DBDataSource();
    
        private DBDataSource() {
        }
    
        public static DBDataSource getInstance() {
            return instance;
        }
    
        // 单例模式end
        // 非主数据库连接池集群池
        private Map<String, DataSource> otherDataSourceMap = new HashMap<String, DataSource>();
        // 主数据库连接池集群池
        private Map<Integer, DataSource> mainDataSourceMap = new HashMap<Integer, DataSource>();
        // 记录数据库负载均衡的配置
        private Map<Integer, Integer> mainDataSourceWeightMap = new HashMap<Integer, Integer>();
        // 记录获取数据库连接的指针
        private int mainDataSourceWeightIndex = 0;
    
        /**
         * 获取连接池
         * 
         * @param bean
         * @return
         * @throws DBException
         */
        public DataSource getDataSource(JdbcPropertiesBean bean) throws DBException {
            if (bean == null) {
                return getDataSource();
            }
            if (bean.getJdbcDriver() == null || bean.getJdbcUrl() == null || bean.getJdbcUserName() == null || bean.getJdbcPassword() == null) {
                logger.error("********数据库配置信息不完整!!!*********");
                logger.error("*********加载默认数据库配置!!!*********");
                return getDataSource();
            }
            DataSource dataSource = (DataSource) otherDataSourceMap.get(bean.toString());
            if (dataSource != null) {
                return dataSource;
            }
            logger.info("*********加载数据库配置***********************");
            logger.info("JdbcDriver   =" + bean.getJdbcDriver());
            logger.info("JdbcUrl      =" + bean.getJdbcUrl());
            logger.info("JdbcUserName =" + bean.getJdbcUserName());
            logger.info("JdbcPassword =" + bean.getJdbcPassword());
            logger.info("JdbcMaxactive=" + bean.getJdbcMaxactive());
            logger.info("JdbcMaxidle  =" + bean.getJdbcMaxidle());
            logger.info("JdbcMaxwait  =" + bean.getJdbcMaxwait());
            BasicDataSource basicDataSource = new BasicDataSource();
            basicDataSource.setDriverClassName(bean.getJdbcDriver());
            basicDataSource.setUrl(bean.getJdbcUrl());
            basicDataSource.setUsername(bean.getJdbcUserName());
            basicDataSource.setPassword(bean.getJdbcPassword());
            basicDataSource.setMaxActive(bean.getJdbcMaxactive());
            basicDataSource.setMaxIdle(bean.getJdbcMaxidle());
            basicDataSource.setMaxWait(bean.getJdbcMaxwait());
            dataSource = basicDataSource;
            logger.info("*********加载数据库配置完成************************");
            otherDataSourceMap.put(bean.toString(), dataSource);
            return dataSource;
        }
    
        /**
         * 获取连接池
         * 
         * @return 连接池
         * @throws DBException
         */
        public DataSource getDataSource() throws DBException {
            String jdbcFileName;
            JdbcPropertiesBean bean;
            DataSource dataSource;
            String jdbcs = ConfigBean.getInstance().getJdbcs();
            if (mainDataSourceMap.isEmpty()) {
                for (int i = 0; i < jdbcs.split(",").length; i++) {
                    jdbcFileName = jdbcs.split(",")[i];
                    bean = JdbcPropertiesManager.getInstance().getJdbcPropertiesBean(jdbcFileName);
                    logger.info("*********加载数据库配置***********************");
                    logger.info("JdbcDriver   =" + bean.getJdbcDriver());
                    logger.info("JdbcUrl      =" + bean.getJdbcUrl());
                    logger.info("JdbcUserName =" + bean.getJdbcUserName());
                    logger.info("JdbcPassword =" + bean.getJdbcPassword());
                    logger.info("JdbcMaxactive=" + bean.getJdbcMaxactive());
                    logger.info("JdbcMaxidle  =" + bean.getJdbcMaxidle());
                    logger.info("JdbcMaxwait  =" + bean.getJdbcMaxwait());
                    logger.info("JdbcWeight   =" + bean.getJdbcWeight());
                    BasicDataSource basicDataSource = new BasicDataSource();
                    basicDataSource.setDriverClassName(bean.getJdbcDriver());
                    basicDataSource.setUrl(bean.getJdbcUrl());
                    basicDataSource.setUsername(bean.getJdbcUserName());
                    basicDataSource.setPassword(bean.getJdbcPassword());
                    basicDataSource.setMaxActive(bean.getJdbcMaxactive());
                    basicDataSource.setMaxIdle(bean.getJdbcMaxidle());
                    basicDataSource.setMaxWait(bean.getJdbcMaxwait());
                    dataSource = basicDataSource;
                    //负载设置关键代码---begin
                    mainDataSourceMap.put(i, dataSource);
                    for (int j = 0; j < bean.getJdbcWeight(); j++) {
                        mainDataSourceWeightMap.put(mainDataSourceWeightMap.size() + 1, i);
                    }
                    //负载设置关键代码---end
                    logger.info("*********加载数据库配置完成************************");
                }
            }
            int mainDataSourceNowIndex;
            try {
                mainDataSourceNowIndex = mainDataSourceWeightMap.get(mainDataSourceWeightIndex % (mainDataSourceWeightMap.size()));
                mainDataSourceWeightIndex++;
                if (mainDataSourceWeightIndex >= mainDataSourceWeightMap.size()) {
                    mainDataSourceWeightIndex = 0;
                }
            } catch (Exception e) {
                mainDataSourceNowIndex = 0;
            }
            return (DataSource) mainDataSourceMap.get(mainDataSourceNowIndex);
        }
    
        /**
         * 清空数据库连接池
         */
        public void clear() {
            otherDataSourceMap.clear();
            mainDataSourceMap.clear();
            mainDataSourceWeightMap.clear();
            mainDataSourceWeightIndex = 0;
        }
    }

      ⑤数据库连接实现

    package com.keji10.core.jdbc.dataSource;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    import javax.sql.DataSource;
    
    import org.apache.log4j.Logger;
    
    import com.keji10.core.exception.DBException;
    import com.keji10.core.jdbc.properties.JdbcPropertiesBean;
    
    /**
     * 类描述:数据库连接实现
     * 
     * @since 1.5
     * @version 1.0
     * @author xuanly
     * 
     */
    public class DBConnection {
        private Logger logger = Logger.getLogger(DBConnection.class.getName());
        // 单例模式begin
        private static DBConnection instance = new DBConnection();
    
        private DBConnection() {
        }
    
        public static DBConnection getInstance() {
            return instance;
        }
    
        // 单例模式end
        /**
         * 获取默认数据库连接
         * 
         * @return 数据库连接
         * @throws DBException
         */
        public Connection getConnection() throws DBException {
            try {
                return DBDataSource.getInstance().getDataSource().getConnection();
            } catch (SQLException e) {
                logger.error(e);
                throw new DBException(e);
            }
        }
    
        /**
         * 根据配置文件获取自定义数据库连接
         * 
         * @param JdbcPropertiesBean
         * @return
         * @throws DBException
         */
        public Connection getConnection(JdbcPropertiesBean JdbcPropertiesBean) throws DBException {
            DataSource dataSource = DBDataSource.getInstance().getDataSource(JdbcPropertiesBean);
            try {
                return dataSource.getConnection();
            } catch (SQLException e) {
                logger.error(e);
                throw new DBException(e);
            }
        }
    
        /**
         * 关闭数据库连接
         * 
         * @throws DBException
         */
        public void close(Connection connection) throws DBException {
            try {
                if (connection == null) {
                    return;
                }
                if (connection.isClosed()) {
                    return;
                }
                if (connection != null) {
                    connection.close();
                    connection = null;
                }
            } catch (SQLException e) {
                logger.error(e);
                throw new DBException(e);
            } finally {
                connection = null;
            }
        }
    
        /**
         * 清空数据库连接池
         */
        public void clear() {
            DBDataSource.getInstance().clear();
        }
    }

    封装框架最核心的部分,莫过于数据库连接的封装。数据库连接就像一条管道,一端连着数据库,一端连接java程序。

    如果一个框架,能够像数据库连接一样,一端连着数据库,一端连着用户的界面,中间无需编辑java代码,即可完成项目开发。

    那这套框架的思路将会为以后的开发,开辟一个新模式。

    计划安排,下一编先把对象映射完成,再写数据库查询的封装。

  • 相关阅读:
    Fiddler抓包9-保存会话(save)
    Selenium2+python自动化61-Chrome您使用的是不受支持的命令行标记:--ignore-certificate-errors
    Fiddler抓包8-打断点(bpu)
    Fiddler抓包7-post请求(json)
    Java图片验证码
    servlet过滤器
    servlet监听器实现在线人数统计
    基于MVC模式的数据库综合练习
    JSTL详解
    初识EL表达式
  • 原文地址:https://www.cnblogs.com/ltlm/p/10208105.html
Copyright © 2020-2023  润新知