資料庫連接池及資料庫連接獲取(架構師的成長之路---第4篇)

来源:https://www.cnblogs.com/ltlm/archive/2019/01/02/10208105.html
-Advertisement-
Play Games

閑話少說,直接列舉問題: ①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代碼,即可完成項目開發。

那這套框架的思路將會為以後的開發,開闢一個新模式。

計劃安排,下一編先把對象映射完成,再寫資料庫查詢的封裝。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • function getBrowserInfo() { var ua = navigator.userAgent.toLocaleLowerCase(); var browserType = null; if (ua.match(/msie/) != null || ua.match(/triden... ...
  • 最近項目不太忙,有時間系統學習了一下rxjs的一些知識,將其中個人認為比較常用的一些操作符mark下來,分享學習 ...
  • 瀏覽器中的JavaScript: 1.基於ECMAscript規範,這個規範規定了語法 2.添加了dom:用來處理文檔 document object model 3.添加了BOM:用於操作瀏覽器 window location histrory navigator Node中的JavaScript ...
  • 身為一個前端攻城獅,是不是經常遇到各種各樣的響應式問題?下麵我們來說一下: 1.響應式跟自適應有什麼區別? 有些人可能還不知道響應式跟自適應的區別,甚至認為他們是同一個東西,其實不是的. 自適應是最早出現的,後面才有了響應式。響應式佈局等於流動網格佈局,而自適應佈局等於使用固定分割點來進行佈局。 如 ...
  • 由於升級了 v0.2 版 GearCase 使用打包工具從 parcel 更換成 vue-cli 3.x。因此打包後發佈 NPM 包的方式與之前有很大的差異,這也導致了在發佈完 GearCase v0.2.2 版本之後,我自己在進行 NPM / Yarn 安裝包時。根本無法通過之前文檔的方式,進行引 ...
  • (1)typeof 和 instanceof 1、typeof 對於基本數據類型(boolean、null、undefined、number、string、symbol)來說,除了 null 都可以顯示正確的類型;對於對象來說,除了函數都會顯示 object。 2、instanceof 是通過原型鏈 ...
  • 這個問題有時候會導致彈出框確定按鈕失效等一系列問題, 解決辦法:失去焦點時將頁面滾動到底層,或者最頂部,個人看實際情況滾動到適合位置 $('input,textarea').on('blur', function () { window.scroll(0, document.body.scrollH ...
  • FaaS介紹 微服務(MicroService)是以專註於單一服務/功能的小型單元塊為基礎,利用模塊化的方式組合成複雜的大型應用服務。 FaaS是Function as a Service的縮寫,可以簡單理解為功能服務化。FaaS提供了一種比微服務更加服務碎片化的軟體架構範式。FaaS可以讓研發只需 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...