c3p0代码动态切换数据源
程序员文章站
2022-07-12 16:11:06
...
public class PARPDatasource implements DataSource, FactoryBean<PARPDatasource> {
private static PARPDatasource parpDatasource = new PARPDatasource();
private static ThreadLocal<String> currrentDatasourceId = new ThreadLocal<String>();
private static Map<String, DataSource> dataSourceStore = new ConcurrentHashMap<String, DataSource>();
private static Log log = LogFactory.getLog(PARPDatasource.class);
public static synchronized void updateDataSource(
Map<String, String> dbSourceInfo) throws Exception {
currrentDatasourceId.set(dbSourceInfo.get("ID_BI_INFO"));
if (!isDataSourceUnchanged(dbSourceInfo)) {
log.info("datasource changed reinit datasourceId="+ getCurrentDataSourceId());
ComboPooledDataSource oldDataSource = (ComboPooledDataSource) dataSourceStore
.get(getCurrentDataSourceId());
dataSourceStore.put(getCurrentDataSourceId(),
initDataSource(dbSourceInfo));
closeQuietly(oldDataSource);
}
}
public static synchronized void refreshDataSource(
Map<String, String> dbSourceInfo) throws Exception {
log.info("datasource refresh reinit");
currrentDatasourceId.set(dbSourceInfo.get("ID_BI_INFO"));
log.info("datasource refresh reinit datasourceId="
+ getCurrentDataSourceId());
ComboPooledDataSource oldDataSource = (ComboPooledDataSource) dataSourceStore
.get(getCurrentDataSourceId());
dataSourceStore.put(getCurrentDataSourceId(),
initDataSource(dbSourceInfo));
closeQuietly(oldDataSource);
}
private static void closeQuietly(ComboPooledDataSource oldDataSource) {
log.info("datasource closeQuietly");
if (oldDataSource != null) {
try {
log.info("datasource closeQuietly start");
oldDataSource.close();
log.info("datasource closeQuietly end");
} catch (Exception e) {
log.error("close datasource error:currentDataSourceId="
+ getCurrentDataSourceId(), e);
}
}
}
private static boolean isDataSourceUnchanged(
Map<String, String> dbSourceInfo) {
ComboPooledDataSource currentDataSource = (ComboPooledDataSource) dataSourceStore
.get(getCurrentDataSourceId());
if (null == currentDataSource) {
return false;
}
return dbSourceInfo.get("JDBC_URL").equals(
currentDataSource.getJdbcUrl())
&& dbSourceInfo.get("USERNAME").equals(
currentDataSource.getUser())
&& dbSourceInfo.get("PASSWORD").equals(
currentDataSource.getPassword());
}
private DataSource getCurrentDataSource() throws SQLException {
try {
return dataSourceStore.get(getCurrentDataSourceId());
} catch (Exception e) {
throw new SQLException(e);
}
}
private static String getCurrentDataSourceId() {
return currrentDatasourceId.get();
}
private static DataSource initDataSource(Map<String, String> dbSourceInfo)
throws Exception {
log.info("datasource initDataSource start");
DriverManager.setLogWriter(new PrintWriter(System.out));
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(dbSourceInfo.get("DRIVER_CLASS"));
ds.setJdbcUrl(dbSourceInfo.get("JDBC_URL"));
ds.setUser(dbSourceInfo.get("USERNAME"));
ds.setPassword(dbSourceInfo.get("PASSWORD"));
ds.setDataSourceName(dbSourceInfo.get("ID_BI_INFO"));
// 初始化时获取5个连接,取�1�7�应在minPoolSize与maxPoolSize之间。Default: 3
ds.setInitialPoolSize(1);
// 连接池中保留的最大连接数。Default: 15
ds.setMaxPoolSize(70);
// 连接池中保留的最小连接数。Default: 5
ds.setMinPoolSize(1);
ds.setMaxStatementsPerConnection(100);
ds.setNumHelperThreads(5);
// <!--如果设为true那么在取得连接的同时将校验连接的有效性。Default: false -->
ds.setTestConnectionOnCheckout(isNotHiveDriver(dbSourceInfo));
// --因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
// 等方法来提升连接测试的性能。Default: false
ds.setTestConnectionOnCheckin(false);
// 每60秒检查所有连接池中的空闲连接。Default: 0 目前我们测试出来是 milliseconds,0表示 不测试
ds.setIdleConnectionTestPeriod(0);
// 最大空闲时间,30分钟内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 单位 seconds
ds.setMaxIdleTime(30 * 60);
// 当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出
// SQLException,如设为0则无限期等待。单位毫秒。Default: 0
ds.setCheckoutTimeout(180 * 1000);
// 定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:
// 测试的表必须在初始数据源的时候就存在。Default: null
if (StringUtils.isNotEmpty(dbSourceInfo.get("TEST_TABLE_QUERY"))){
ds.setPreferredTestQuery(dbSourceInfo.get("TEST_TABLE_QUERY"));
}else{
ds.setPreferredTestQuery("select 1 from dual");
}
//ds.setAcquireRetryAttempts(10);//尝试30次连接
//ds.setAcquireRetryDelay(100);//每100ms尝试一次
ds.setBreakAfterAcquireFailure(true);// 获取连接失败关闭数据源,网络异常需要重启或者重新配置数据源
//ds.setUnreturnedConnectionTimeout(30);//自动超时回收Connection (强烈推荐) default : 0 单位 s
log.info("datasource initDataSource end");//
return ds;
}
private static boolean isNotHiveDriver(Map<String, String> dbSourceInfo) {
boolean flag=true;
if("org.apache.hive.jdbc.HiveDriver".equals(dbSourceInfo
.get("DRIVER_CLASS"))){
flag=false;
}else if("org.postgresql.Driver".equals(dbSourceInfo
.get("DRIVER_CLASS"))){
flag=false;
}
return flag;
}
@Override
public Connection getConnection() throws SQLException {
log.info("...getConnection..currrentDatasourceId...."+getCurrentDataSourceId());
return getCurrentDataSource().getConnection();
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
return getCurrentDataSource().getConnection(username, password);
}
@Override
public PARPDatasource getObject() throws Exception {
return parpDatasource;
}
@Override
public Class<PARPDatasource> getObjectType() {
return PARPDatasource.class;
}
@Override
public boolean isSingleton() {
return true;
}
public static PARPDatasource getInstance() {
return parpDatasource;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return getCurrentDataSource().getLogWriter();
}
@Override
public int getLoginTimeout() throws SQLException {
return getCurrentDataSource().getLoginTimeout();
}
@Override
public void setLogWriter(PrintWriter printWriter) throws SQLException {
getCurrentDataSource().setLogWriter(printWriter);
}
@Override
public void setLoginTimeout(int loginTimeout) throws SQLException {
getCurrentDataSource().setLoginTimeout(loginTimeout);
}
@Override
public boolean isWrapperFor(Class<?> clazz) throws SQLException {
return getCurrentDataSource().isWrapperFor(clazz);
}
@Override
public <T> T unwrap(Class<T> clazz) throws SQLException {
return getCurrentDataSource().unwrap(clazz);
}
public String getDriverClassName() throws Exception {
return ((ComboPooledDataSource) getCurrentDataSource())
.getDriverClass();
}
@SuppressWarnings({"unused", "finally"})
public static boolean validateDB(Map paramMap) {
Connection conn = null;
try {
log.info("------- validateDB start -------------");
String userPwdSource = (String) paramMap.get("userPwdSource");
Class.forName((String) paramMap.get("driverClass"));
String pwd = (String) paramMap.get("dbPwd");
if ("cyberark".equals(userPwdSource)) {
pwd=ParpCyberarkUtil.getV9CyberarkPassword(
(String)paramMap.get("requestPowdPath"),
(String) paramMap.get("cyberarkAuthname"),
(String) paramMap.get("cyberarkCredappId"),
(String) paramMap.get("cyberarkPwdKey"),
(String) paramMap.get("cyberarkPwdSafe"),
(String) paramMap.get("cyberarkPwdFolder"),
pwd);
}
DriverManager.setLoginTimeout(60);// 设置超时为1秒
conn = DriverManager.getConnection(
(String) paramMap.get("driverUrl"),
(String) paramMap.get("userName"), pwd);
log.info("------- validateDB connect -------------" + conn);
if (conn != null) {
log.info("------- validateDB end true -------------");
return true;
}
} catch (Exception e) {
log.error("validateDB connect exception url="
+ paramMap.get("driverUrl") + "&user="
+ paramMap.get("userName"));
log.error(e);
log.info("validateDB error : " + e.getMessage());
log.error(e.getMessage(), e.getCause());
log.info("------- validateDB connect false -------------", e);
return false;
} finally {
try {
conn.close();
} catch (Exception e) {
}
}
log.info("------- validateDB end false -------------");
return false;
}
}
private static PARPDatasource parpDatasource = new PARPDatasource();
private static ThreadLocal<String> currrentDatasourceId = new ThreadLocal<String>();
private static Map<String, DataSource> dataSourceStore = new ConcurrentHashMap<String, DataSource>();
private static Log log = LogFactory.getLog(PARPDatasource.class);
public static synchronized void updateDataSource(
Map<String, String> dbSourceInfo) throws Exception {
currrentDatasourceId.set(dbSourceInfo.get("ID_BI_INFO"));
if (!isDataSourceUnchanged(dbSourceInfo)) {
log.info("datasource changed reinit datasourceId="+ getCurrentDataSourceId());
ComboPooledDataSource oldDataSource = (ComboPooledDataSource) dataSourceStore
.get(getCurrentDataSourceId());
dataSourceStore.put(getCurrentDataSourceId(),
initDataSource(dbSourceInfo));
closeQuietly(oldDataSource);
}
}
public static synchronized void refreshDataSource(
Map<String, String> dbSourceInfo) throws Exception {
log.info("datasource refresh reinit");
currrentDatasourceId.set(dbSourceInfo.get("ID_BI_INFO"));
log.info("datasource refresh reinit datasourceId="
+ getCurrentDataSourceId());
ComboPooledDataSource oldDataSource = (ComboPooledDataSource) dataSourceStore
.get(getCurrentDataSourceId());
dataSourceStore.put(getCurrentDataSourceId(),
initDataSource(dbSourceInfo));
closeQuietly(oldDataSource);
}
private static void closeQuietly(ComboPooledDataSource oldDataSource) {
log.info("datasource closeQuietly");
if (oldDataSource != null) {
try {
log.info("datasource closeQuietly start");
oldDataSource.close();
log.info("datasource closeQuietly end");
} catch (Exception e) {
log.error("close datasource error:currentDataSourceId="
+ getCurrentDataSourceId(), e);
}
}
}
private static boolean isDataSourceUnchanged(
Map<String, String> dbSourceInfo) {
ComboPooledDataSource currentDataSource = (ComboPooledDataSource) dataSourceStore
.get(getCurrentDataSourceId());
if (null == currentDataSource) {
return false;
}
return dbSourceInfo.get("JDBC_URL").equals(
currentDataSource.getJdbcUrl())
&& dbSourceInfo.get("USERNAME").equals(
currentDataSource.getUser())
&& dbSourceInfo.get("PASSWORD").equals(
currentDataSource.getPassword());
}
private DataSource getCurrentDataSource() throws SQLException {
try {
return dataSourceStore.get(getCurrentDataSourceId());
} catch (Exception e) {
throw new SQLException(e);
}
}
private static String getCurrentDataSourceId() {
return currrentDatasourceId.get();
}
private static DataSource initDataSource(Map<String, String> dbSourceInfo)
throws Exception {
log.info("datasource initDataSource start");
DriverManager.setLogWriter(new PrintWriter(System.out));
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(dbSourceInfo.get("DRIVER_CLASS"));
ds.setJdbcUrl(dbSourceInfo.get("JDBC_URL"));
ds.setUser(dbSourceInfo.get("USERNAME"));
ds.setPassword(dbSourceInfo.get("PASSWORD"));
ds.setDataSourceName(dbSourceInfo.get("ID_BI_INFO"));
// 初始化时获取5个连接,取�1�7�应在minPoolSize与maxPoolSize之间。Default: 3
ds.setInitialPoolSize(1);
// 连接池中保留的最大连接数。Default: 15
ds.setMaxPoolSize(70);
// 连接池中保留的最小连接数。Default: 5
ds.setMinPoolSize(1);
ds.setMaxStatementsPerConnection(100);
ds.setNumHelperThreads(5);
// <!--如果设为true那么在取得连接的同时将校验连接的有效性。Default: false -->
ds.setTestConnectionOnCheckout(isNotHiveDriver(dbSourceInfo));
// --因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
// 等方法来提升连接测试的性能。Default: false
ds.setTestConnectionOnCheckin(false);
// 每60秒检查所有连接池中的空闲连接。Default: 0 目前我们测试出来是 milliseconds,0表示 不测试
ds.setIdleConnectionTestPeriod(0);
// 最大空闲时间,30分钟内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 单位 seconds
ds.setMaxIdleTime(30 * 60);
// 当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出
// SQLException,如设为0则无限期等待。单位毫秒。Default: 0
ds.setCheckoutTimeout(180 * 1000);
// 定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:
// 测试的表必须在初始数据源的时候就存在。Default: null
if (StringUtils.isNotEmpty(dbSourceInfo.get("TEST_TABLE_QUERY"))){
ds.setPreferredTestQuery(dbSourceInfo.get("TEST_TABLE_QUERY"));
}else{
ds.setPreferredTestQuery("select 1 from dual");
}
//ds.setAcquireRetryAttempts(10);//尝试30次连接
//ds.setAcquireRetryDelay(100);//每100ms尝试一次
ds.setBreakAfterAcquireFailure(true);// 获取连接失败关闭数据源,网络异常需要重启或者重新配置数据源
//ds.setUnreturnedConnectionTimeout(30);//自动超时回收Connection (强烈推荐) default : 0 单位 s
log.info("datasource initDataSource end");//
return ds;
}
private static boolean isNotHiveDriver(Map<String, String> dbSourceInfo) {
boolean flag=true;
if("org.apache.hive.jdbc.HiveDriver".equals(dbSourceInfo
.get("DRIVER_CLASS"))){
flag=false;
}else if("org.postgresql.Driver".equals(dbSourceInfo
.get("DRIVER_CLASS"))){
flag=false;
}
return flag;
}
@Override
public Connection getConnection() throws SQLException {
log.info("...getConnection..currrentDatasourceId...."+getCurrentDataSourceId());
return getCurrentDataSource().getConnection();
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
return getCurrentDataSource().getConnection(username, password);
}
@Override
public PARPDatasource getObject() throws Exception {
return parpDatasource;
}
@Override
public Class<PARPDatasource> getObjectType() {
return PARPDatasource.class;
}
@Override
public boolean isSingleton() {
return true;
}
public static PARPDatasource getInstance() {
return parpDatasource;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return getCurrentDataSource().getLogWriter();
}
@Override
public int getLoginTimeout() throws SQLException {
return getCurrentDataSource().getLoginTimeout();
}
@Override
public void setLogWriter(PrintWriter printWriter) throws SQLException {
getCurrentDataSource().setLogWriter(printWriter);
}
@Override
public void setLoginTimeout(int loginTimeout) throws SQLException {
getCurrentDataSource().setLoginTimeout(loginTimeout);
}
@Override
public boolean isWrapperFor(Class<?> clazz) throws SQLException {
return getCurrentDataSource().isWrapperFor(clazz);
}
@Override
public <T> T unwrap(Class<T> clazz) throws SQLException {
return getCurrentDataSource().unwrap(clazz);
}
public String getDriverClassName() throws Exception {
return ((ComboPooledDataSource) getCurrentDataSource())
.getDriverClass();
}
@SuppressWarnings({"unused", "finally"})
public static boolean validateDB(Map paramMap) {
Connection conn = null;
try {
log.info("------- validateDB start -------------");
String userPwdSource = (String) paramMap.get("userPwdSource");
Class.forName((String) paramMap.get("driverClass"));
String pwd = (String) paramMap.get("dbPwd");
if ("cyberark".equals(userPwdSource)) {
pwd=ParpCyberarkUtil.getV9CyberarkPassword(
(String)paramMap.get("requestPowdPath"),
(String) paramMap.get("cyberarkAuthname"),
(String) paramMap.get("cyberarkCredappId"),
(String) paramMap.get("cyberarkPwdKey"),
(String) paramMap.get("cyberarkPwdSafe"),
(String) paramMap.get("cyberarkPwdFolder"),
pwd);
}
DriverManager.setLoginTimeout(60);// 设置超时为1秒
conn = DriverManager.getConnection(
(String) paramMap.get("driverUrl"),
(String) paramMap.get("userName"), pwd);
log.info("------- validateDB connect -------------" + conn);
if (conn != null) {
log.info("------- validateDB end true -------------");
return true;
}
} catch (Exception e) {
log.error("validateDB connect exception url="
+ paramMap.get("driverUrl") + "&user="
+ paramMap.get("userName"));
log.error(e);
log.info("validateDB error : " + e.getMessage());
log.error(e.getMessage(), e.getCause());
log.info("------- validateDB connect false -------------", e);
return false;
} finally {
try {
conn.close();
} catch (Exception e) {
}
}
log.info("------- validateDB end false -------------");
return false;
}
}