数据库连接池及数据库连接获取(架构师的成长之路---第4篇)
程序员文章站
2022-05-04 13:30:37
闲话少说,直接列举问题: ①AB两台数据库服务器做集群,由于两台服务器配置不一样,如何在代码中要实现每访问服务器A的数据库2次,才能访问服务器B的数据库1次。 ②AB两台数据库服务器做读写分离,如何在代码中控制,查询数据使用服务器A的数据库连接,增删改使用服务器B的数据库连接。 代码结构: 代码实现 ......
闲话少说,直接列举问题:
①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代码,即可完成项目开发。
那这套框架的思路将会为以后的开发,开辟一个新模式。
计划安排,下一编先把对象映射完成,再写数据库查询的封装。
上一篇: 项目中必须对应的隐性需求-安全漏洞修复
下一篇: 设计模式系列- 抽象工厂模式