mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix code
This commit is contained in:
parent
4b83504e50
commit
494c70b9e6
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
* Hutool is licensed under Mulan PSL v2.
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
@ -10,22 +10,24 @@
|
|||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.dromara.hutool.core.exception;
|
package org.dromara.hutool.core.pool;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.exception.HutoolException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 未初始化异常
|
* 对象池异常
|
||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class NotInitedException extends HutoolException {
|
public class PoolException extends HutoolException {
|
||||||
private static final long serialVersionUID = 8247610319171014183L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
*
|
*
|
||||||
* @param e 异常
|
* @param e 异常
|
||||||
*/
|
*/
|
||||||
public NotInitedException(final Throwable e) {
|
public PoolException(final Throwable e) {
|
||||||
super(e);
|
super(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +36,7 @@ public class NotInitedException extends HutoolException {
|
|||||||
*
|
*
|
||||||
* @param message 消息
|
* @param message 消息
|
||||||
*/
|
*/
|
||||||
public NotInitedException(final String message) {
|
public PoolException(final String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ public class NotInitedException extends HutoolException {
|
|||||||
* @param messageTemplate 消息模板
|
* @param messageTemplate 消息模板
|
||||||
* @param params 参数
|
* @param params 参数
|
||||||
*/
|
*/
|
||||||
public NotInitedException(final String messageTemplate, final Object... params) {
|
public PoolException(final String messageTemplate, final Object... params) {
|
||||||
super(messageTemplate, params);
|
super(messageTemplate, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ public class NotInitedException extends HutoolException {
|
|||||||
* @param message 消息
|
* @param message 消息
|
||||||
* @param cause 被包装的子异常
|
* @param cause 被包装的子异常
|
||||||
*/
|
*/
|
||||||
public NotInitedException(final String message, final Throwable cause) {
|
public PoolException(final String message, final Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +68,7 @@ public class NotInitedException extends HutoolException {
|
|||||||
* @param enableSuppression 是否启用抑制
|
* @param enableSuppression 是否启用抑制
|
||||||
* @param writableStackTrace 堆栈跟踪是否应该是可写的
|
* @param writableStackTrace 堆栈跟踪是否应该是可写的
|
||||||
*/
|
*/
|
||||||
public NotInitedException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) {
|
public PoolException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) {
|
||||||
super(message, cause, enableSuppression, writableStackTrace);
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +79,7 @@ public class NotInitedException extends HutoolException {
|
|||||||
* @param messageTemplate 消息模板
|
* @param messageTemplate 消息模板
|
||||||
* @param params 参数
|
* @param params 参数
|
||||||
*/
|
*/
|
||||||
public NotInitedException(final Throwable cause, final String messageTemplate, final Object... params) {
|
public PoolException(final Throwable cause, final String messageTemplate, final Object... params) {
|
||||||
super(cause, messageTemplate, params);
|
super(cause, messageTemplate, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,11 +12,7 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.core.pool.partition;
|
package org.dromara.hutool.core.pool.partition;
|
||||||
|
|
||||||
import org.dromara.hutool.core.exception.HutoolException;
|
import org.dromara.hutool.core.pool.*;
|
||||||
import org.dromara.hutool.core.pool.ObjectFactory;
|
|
||||||
import org.dromara.hutool.core.pool.ObjectPool;
|
|
||||||
import org.dromara.hutool.core.pool.PoolConfig;
|
|
||||||
import org.dromara.hutool.core.pool.Poolable;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
@ -99,7 +95,7 @@ public class PoolPartition<T> implements ObjectPool<T> {
|
|||||||
poolable = waitingPoll();
|
poolable = waitingPoll();
|
||||||
if (null == poolable) {
|
if (null == poolable) {
|
||||||
// 池空间达到最大值,但是无可用对象
|
// 池空间达到最大值,但是无可用对象
|
||||||
throw new HutoolException("Pool exhausted!");
|
throw new PoolException("Pool exhausted!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +118,7 @@ public class PoolPartition<T> implements ObjectPool<T> {
|
|||||||
try {
|
try {
|
||||||
this.queue.put(poolable);
|
this.queue.put(poolable);
|
||||||
} catch (final InterruptedException e) {
|
} catch (final InterruptedException e) {
|
||||||
throw new HutoolException(e);
|
throw new PoolException(e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 对象不可用
|
// 对象不可用
|
||||||
@ -150,7 +146,7 @@ public class PoolPartition<T> implements ObjectPool<T> {
|
|||||||
}
|
}
|
||||||
total += increaseSize;
|
total += increaseSize;
|
||||||
} catch (final InterruptedException e) {
|
} catch (final InterruptedException e) {
|
||||||
throw new HutoolException(e);
|
throw new PoolException(e);
|
||||||
}
|
}
|
||||||
return increaseSize;
|
return increaseSize;
|
||||||
}
|
}
|
||||||
@ -208,9 +204,9 @@ public class PoolPartition<T> implements ObjectPool<T> {
|
|||||||
* 等待的时间取决于{@link PoolConfig#getMaxWait()},小于等于0时一直等待,否则等待给定毫秒数
|
* 等待的时间取决于{@link PoolConfig#getMaxWait()},小于等于0时一直等待,否则等待给定毫秒数
|
||||||
*
|
*
|
||||||
* @return 取出的池对象
|
* @return 取出的池对象
|
||||||
* @throws HutoolException 中断异常
|
* @throws PoolException 中断异常
|
||||||
*/
|
*/
|
||||||
private Poolable<T> waitingPoll() throws HutoolException {
|
private Poolable<T> waitingPoll() throws PoolException {
|
||||||
final long maxWait = this.config.getMaxWait();
|
final long maxWait = this.config.getMaxWait();
|
||||||
try {
|
try {
|
||||||
if (maxWait <= 0) {
|
if (maxWait <= 0) {
|
||||||
@ -218,7 +214,7 @@ public class PoolPartition<T> implements ObjectPool<T> {
|
|||||||
}
|
}
|
||||||
return this.queue.poll(maxWait, TimeUnit.MILLISECONDS);
|
return this.queue.poll(maxWait, TimeUnit.MILLISECONDS);
|
||||||
} catch (final InterruptedException e) {
|
} catch (final InterruptedException e) {
|
||||||
throw new HutoolException(e);
|
throw new PoolException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1325,7 +1325,7 @@ public class CharSequenceUtil extends StrValidator {
|
|||||||
* @see #appendIfMissing(CharSequence, CharSequence, CharSequence...)
|
* @see #appendIfMissing(CharSequence, CharSequence, CharSequence...)
|
||||||
*/
|
*/
|
||||||
public static String addSuffixIfNot(final CharSequence str, final CharSequence suffix) {
|
public static String addSuffixIfNot(final CharSequence str, final CharSequence suffix) {
|
||||||
return appendIfMissing(str, suffix, suffix);
|
return appendIfMissing(str, suffix);
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
@ -1,224 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
|
||||||
* Hutool is licensed under Mulan PSL v2.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
|
||||||
* https://license.coscl.org.cn/MulanPSL2
|
|
||||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
||||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
||||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the Mulan PSL v2 for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.dromara.hutool.db.ds;
|
|
||||||
|
|
||||||
import org.dromara.hutool.core.lang.Assert;
|
|
||||||
import org.dromara.hutool.core.map.MapUtil;
|
|
||||||
import org.dromara.hutool.core.map.SafeConcurrentHashMap;
|
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
|
||||||
import org.dromara.hutool.db.DbRuntimeException;
|
|
||||||
import org.dromara.hutool.db.DbUtil;
|
|
||||||
import org.dromara.hutool.db.GlobalDbConfig;
|
|
||||||
import org.dromara.hutool.db.driver.DriverUtil;
|
|
||||||
import org.dromara.hutool.setting.Setting;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 抽象数据源工厂<br>
|
|
||||||
* 此工厂抽象类用于实现数据源的缓存,当用户多次调用{@link #getDataSource(String)} 时,工厂只需创建一次即可。<br>
|
|
||||||
* 数据源是与配置文件中的分组相关的,每个分组的数据源相互独立,也就是每个分组的数据源是单例存在的。
|
|
||||||
*
|
|
||||||
* @author looly
|
|
||||||
*/
|
|
||||||
public abstract class AbstractDSFactory implements DSFactory {
|
|
||||||
private static final long serialVersionUID = -6407302276272379881L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据源名
|
|
||||||
*/
|
|
||||||
protected final String dataSourceName;
|
|
||||||
/**
|
|
||||||
* 数据库连接配置文件
|
|
||||||
*/
|
|
||||||
private final Setting setting;
|
|
||||||
/**
|
|
||||||
* 数据源池
|
|
||||||
*/
|
|
||||||
private final Map<String, DSWrapper> dsMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造
|
|
||||||
*
|
|
||||||
* @param dataSourceName 数据源名称
|
|
||||||
* @param dataSourceClass 数据库连接池实现类,用于检测所提供的DataSource类是否存在,当传入的DataSource类不存在时抛出ClassNotFoundException<br>
|
|
||||||
* 此参数的作用是在detectDSFactory方法自动检测所用连接池时,如果实现类不存在,调用此方法会自动抛出异常,从而切换到下一种连接池的检测。
|
|
||||||
* @param setting 数据库连接配置,如果为{@code null},则读取全局自定义或默认配置
|
|
||||||
*/
|
|
||||||
public AbstractDSFactory(final String dataSourceName, final Class<? extends DataSource> dataSourceClass, Setting setting) {
|
|
||||||
//此参数的作用是在detectDSFactory方法自动检测所用连接池时,如果实现类不存在,调用此方法会自动抛出异常,从而切换到下一种连接池的检测。
|
|
||||||
Assert.notNull(dataSourceClass);
|
|
||||||
|
|
||||||
this.dataSourceName = dataSourceName;
|
|
||||||
|
|
||||||
if (null == setting) {
|
|
||||||
setting = GlobalDbConfig.createDbSetting();
|
|
||||||
}
|
|
||||||
// 读取配置,用于SQL打印
|
|
||||||
DbUtil.setShowSqlGlobal(setting);
|
|
||||||
this.setting = setting;
|
|
||||||
|
|
||||||
this.dsMap = new SafeConcurrentHashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取配置,用于自定义添加配置项
|
|
||||||
*
|
|
||||||
* @return Setting
|
|
||||||
* @since 4.0.3
|
|
||||||
*/
|
|
||||||
public Setting getSetting() {
|
|
||||||
return this.setting;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDataSourceName() {
|
|
||||||
return this.dataSourceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataSource getDataSource(String group) {
|
|
||||||
if (group == null) {
|
|
||||||
group = StrUtil.EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果已经存在已有数据源(连接池)直接返回
|
|
||||||
return dsMap.computeIfAbsent(group, this::_createDataSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
synchronized public void closeDataSource(String group) {
|
|
||||||
if (group == null) {
|
|
||||||
group = StrUtil.EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
final DSWrapper ds = dsMap.get(group);
|
|
||||||
if (ds != null) {
|
|
||||||
ds.close();
|
|
||||||
dsMap.remove(group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
if (MapUtil.isNotEmpty(dsMap)) {
|
|
||||||
final Collection<DSWrapper> values = dsMap.values();
|
|
||||||
for (final DSWrapper ds : values) {
|
|
||||||
ds.close();
|
|
||||||
}
|
|
||||||
dsMap.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
final int prime = 31;
|
|
||||||
int result = 1;
|
|
||||||
result = prime * result + ((dataSourceName == null) ? 0 : dataSourceName.hashCode());
|
|
||||||
result = prime * result + ((setting == null) ? 0 : setting.hashCode());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (obj == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (getClass() != obj.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final AbstractDSFactory other = (AbstractDSFactory) obj;
|
|
||||||
if (dataSourceName == null) {
|
|
||||||
if (other.dataSourceName != null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (!dataSourceName.equals(other.dataSourceName)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (setting == null) {
|
|
||||||
return other.setting == null;
|
|
||||||
} else {
|
|
||||||
return setting.equals(other.setting);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建新的{@link DataSource}<br>
|
|
||||||
* 子类通过实现此方法,创建一个对接连接池的数据源
|
|
||||||
*
|
|
||||||
* @param jdbcUrl JDBC连接字符串
|
|
||||||
* @param driver 数据库驱动类名
|
|
||||||
* @param user 用户名
|
|
||||||
* @param pass 密码
|
|
||||||
* @param poolSetting 分组下的连接池配置文件
|
|
||||||
* @return {@link DataSource}
|
|
||||||
*/
|
|
||||||
protected abstract DataSource createDataSource(
|
|
||||||
String jdbcUrl, String driver, String user, String pass, Setting poolSetting);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建数据源,对于不同连接池名称的的差异做兼容,如用户配置user和username都表示用户名
|
|
||||||
*
|
|
||||||
* @param group 分组
|
|
||||||
* @return {@link DSWrapper} 数据源包装
|
|
||||||
*/
|
|
||||||
private DSWrapper _createDataSource(String group) {
|
|
||||||
if (group == null) {
|
|
||||||
group = StrUtil.EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Setting config = setting.getSetting(group);
|
|
||||||
if (MapUtil.isEmpty(config)) {
|
|
||||||
throw new DbRuntimeException("No config for group: [{}]", group);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 基本信息
|
|
||||||
final String url = config.getAndRemove(DSKeys.KEY_ALIAS_URL);
|
|
||||||
if (StrUtil.isBlank(url)) {
|
|
||||||
throw new DbRuntimeException("No JDBC URL for group: [{}]", group);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移除用户可能误加入的show sql配置项
|
|
||||||
// issue#I3VW0R@Gitee
|
|
||||||
removeShowSqlParams(config);
|
|
||||||
|
|
||||||
// 自动识别Driver
|
|
||||||
String driver = config.getAndRemove(DSKeys.KEY_ALIAS_DRIVER);
|
|
||||||
if (StrUtil.isBlank(driver)) {
|
|
||||||
driver = DriverUtil.identifyDriver(url);
|
|
||||||
}
|
|
||||||
final String user = config.getAndRemove(DSKeys.KEY_ALIAS_USER);
|
|
||||||
final String pass = config.getAndRemove(DSKeys.KEY_ALIAS_PASSWORD);
|
|
||||||
|
|
||||||
return DSWrapper.wrap(createDataSource(url, driver, user, pass, config), driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 移除配置文件中的Show SQL相关配置项<br>
|
|
||||||
* 此方法用于移除用户配置在分组下的配置项目
|
|
||||||
*
|
|
||||||
* @param setting 配置项
|
|
||||||
* @since 5.7.2
|
|
||||||
*/
|
|
||||||
private static void removeShowSqlParams(final Setting setting) {
|
|
||||||
setting.remove(DSKeys.KEY_SHOW_SQL);
|
|
||||||
setting.remove(DSKeys.KEY_FORMAT_SQL);
|
|
||||||
setting.remove(DSKeys.KEY_SHOW_PARAMS);
|
|
||||||
setting.remove(DSKeys.KEY_SQL_LEVEL);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
* Hutool is licensed under Mulan PSL v2.
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
@ -12,17 +12,12 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.db.ds;
|
package org.dromara.hutool.db.ds;
|
||||||
|
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
|
||||||
import org.dromara.hutool.setting.Setting;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import java.io.Closeable;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多数据源工厂方法接口,借助不同配置,同一个工厂可以连接多个相同或不同的数据库,但是连接池只能使用一种。<br>
|
* 多数据源{@link DataSource}工厂方法接口,借助不同配置,同一个工厂可以连接多个相同或不同的数据库,但是连接池只能使用一种。<br>
|
||||||
* 通过实现{@link #getDataSource(String)} 方法完成数据源的获取。<br>
|
* 通过实现{@link #createDataSource(DbConfig)} 方法完成数据源的创建。关系如下:<br>
|
||||||
* 如果{@link DataSource} 的实现是数据库连接池库,应该在getDataSource调用时创建数据源并缓存,关系如下:
|
|
||||||
* <pre>
|
* <pre>
|
||||||
* DSFactory
|
* DSFactory
|
||||||
* _____________________|____________________
|
* _____________________|____________________
|
||||||
@ -33,13 +28,9 @@ import java.io.Serializable;
|
|||||||
* MySQL SQLite SQLServer XXXDB XXXDB2
|
* MySQL SQLite SQLServer XXXDB XXXDB2
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>
|
|
||||||
* 工厂创建请使用{@link DSUtil#createFactory(Setting)}
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public interface DSFactory extends Closeable, Serializable {
|
public interface DSFactory extends Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取自定义的数据源名称,用于识别连接池
|
* 获取自定义的数据源名称,用于识别连接池
|
||||||
@ -49,33 +40,10 @@ public interface DSFactory extends Closeable, Serializable {
|
|||||||
String getDataSourceName();
|
String getDataSourceName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得默认数据源,即""分组的数据源
|
* 创建数据源
|
||||||
*
|
*
|
||||||
* @return 数据源
|
* @param config 数据库配置
|
||||||
|
* @return {@link DataSource}
|
||||||
*/
|
*/
|
||||||
default DataSource getDataSource() {
|
DataSource createDataSource(DbConfig config);
|
||||||
return getDataSource(StrUtil.EMPTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得分组对应数据源
|
|
||||||
*
|
|
||||||
* @param group 分组名
|
|
||||||
* @return 数据源
|
|
||||||
*/
|
|
||||||
DataSource getDataSource(String group);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关闭默认数据源(空组)
|
|
||||||
*/
|
|
||||||
default void closeDataSource() {
|
|
||||||
closeDataSource(StrUtil.EMPTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关闭(归还)对应数据源
|
|
||||||
*
|
|
||||||
* @param group 分组
|
|
||||||
*/
|
|
||||||
void closeDataSource(String group);
|
|
||||||
}
|
}
|
||||||
|
265
hutool-db/src/main/java/org/dromara/hutool/db/ds/DSPool.java
Normal file
265
hutool-db/src/main/java/org/dromara/hutool/db/ds/DSPool.java
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.db.ds;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.io.IoUtil;
|
||||||
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
|
import org.dromara.hutool.core.map.SafeConcurrentHashMap;
|
||||||
|
import org.dromara.hutool.core.spi.SpiUtil;
|
||||||
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
import org.dromara.hutool.db.DbRuntimeException;
|
||||||
|
import org.dromara.hutool.db.GlobalDbConfig;
|
||||||
|
import org.dromara.hutool.db.driver.DriverUtil;
|
||||||
|
import org.dromara.hutool.log.LogUtil;
|
||||||
|
import org.dromara.hutool.setting.Setting;
|
||||||
|
import org.dromara.hutool.setting.props.Props;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据源池,用于支持多数据源。<br>
|
||||||
|
* 在指定Setting中配置多个数据源时,通过分组(group)区分<br>
|
||||||
|
* 每次获得一个数据源则缓存在pool中,确保数据源保持单例状态。
|
||||||
|
*
|
||||||
|
* @author Looly
|
||||||
|
* @since 6.0.0
|
||||||
|
*/
|
||||||
|
public class DSPool implements Closeable {
|
||||||
|
|
||||||
|
private static final String CONNECTION_PREFIX = "connection.";
|
||||||
|
|
||||||
|
private static class SingletonHolder {
|
||||||
|
private static final DSPool INSTANCE = new DSPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单例池对象
|
||||||
|
*
|
||||||
|
* @return 数据源池
|
||||||
|
*/
|
||||||
|
public static DSPool getInstance() {
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库连接配置文件
|
||||||
|
*/
|
||||||
|
private final Setting setting;
|
||||||
|
/**
|
||||||
|
* 数据源池
|
||||||
|
*/
|
||||||
|
private final Map<String, DSWrapper> pool;
|
||||||
|
/**
|
||||||
|
* 连接工厂
|
||||||
|
*/
|
||||||
|
private DSFactory factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造,通过SPI方式自动获取用户引入的连接池,使用classpath:db.setting
|
||||||
|
*/
|
||||||
|
public DSPool() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造,通过SPI方式自动获取用户引入的连接池
|
||||||
|
*
|
||||||
|
* @param setting 数据库配置,支持多数据源,{@code null}表示读取classpath:db.setting
|
||||||
|
*/
|
||||||
|
public DSPool(final Setting setting) {
|
||||||
|
this(setting, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param setting 数据库配置,支持多数据源,{@code null}表示读取classpath:db.setting
|
||||||
|
* @param factory 数据源工厂,用于创建数据源,{@code null}表示使用SPI自动获取
|
||||||
|
*/
|
||||||
|
public DSPool(final Setting setting, final DSFactory factory) {
|
||||||
|
this.setting = null != setting ? setting : GlobalDbConfig.createDbSetting();
|
||||||
|
this.factory = null != factory ? factory : SpiUtil.loadFirstAvailable(DSFactory.class);
|
||||||
|
this.pool = new SafeConcurrentHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取配置,用于自定义添加配置项
|
||||||
|
*
|
||||||
|
* @return Setting
|
||||||
|
* @since 4.0.3
|
||||||
|
*/
|
||||||
|
public Setting getSetting() {
|
||||||
|
return this.setting;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据源名称,用于识别当前使用连接池类型
|
||||||
|
*
|
||||||
|
* @return 数据源名称
|
||||||
|
*/
|
||||||
|
public String getDataSourceName() {
|
||||||
|
return this.factory.getDataSourceName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置自定义的{@link DSFactory}
|
||||||
|
*
|
||||||
|
* @param factory {@link DSFactory}
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public DSPool setFactory(final DSFactory factory) {
|
||||||
|
this.factory = factory;
|
||||||
|
LogUtil.debug("Custom use [{}] DataSource.", factory.getDataSourceName());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定分组的数据源,单例获取
|
||||||
|
*
|
||||||
|
* @param group 分组,{@code null}表示默认分组
|
||||||
|
* @return 数据源
|
||||||
|
*/
|
||||||
|
public DataSource getDataSource(String group) {
|
||||||
|
if (group == null) {
|
||||||
|
group = StrUtil.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果已经存在已有数据源(连接池)直接返回
|
||||||
|
return pool.computeIfAbsent(group, this::createDSWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭指定数据源
|
||||||
|
*
|
||||||
|
* @param group 分组
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public DSPool closeDataSource(String group) {
|
||||||
|
if (group == null) {
|
||||||
|
group = StrUtil.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 此处线程安全,任意线程进入一旦remove完成,后续线程调用remove后都为null
|
||||||
|
final DSWrapper removed = pool.remove(group);
|
||||||
|
if (null != removed) {
|
||||||
|
IoUtil.closeQuietly(removed);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
final Map<String, DSWrapper> pool = this.pool;
|
||||||
|
if (MapUtil.isNotEmpty(pool)) {
|
||||||
|
// 此处线程安全,多线程调用可能多次调用clear,不影响
|
||||||
|
final Collection<DSWrapper> values = pool.values();
|
||||||
|
pool.clear();
|
||||||
|
for (final DSWrapper ds : values) {
|
||||||
|
ds.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建数据源,对于不同连接池名称的的差异做兼容,如用户配置user和username都表示用户名
|
||||||
|
*
|
||||||
|
* @param group 分组,{@code null}表示默认分组
|
||||||
|
* @return {@link DSWrapper} 数据源包装
|
||||||
|
*/
|
||||||
|
private DSWrapper createDSWrapper(String group) {
|
||||||
|
if (group == null) {
|
||||||
|
group = StrUtil.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Setting subSetting = setting.getSetting(group);
|
||||||
|
if (MapUtil.isEmpty(subSetting)) {
|
||||||
|
throw new DbRuntimeException("No config for group: [{}]", group);
|
||||||
|
}
|
||||||
|
|
||||||
|
final DbConfig dbConfig = toDbConfig(subSetting);
|
||||||
|
|
||||||
|
return DSWrapper.wrap(factory.createDataSource(dbConfig), dbConfig.getDriver());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Setting}数据库配置 转 {@link DbConfig}
|
||||||
|
*
|
||||||
|
* @param setting {@link Setting}数据库配置
|
||||||
|
* @return {@link DbConfig}
|
||||||
|
*/
|
||||||
|
private static DbConfig toDbConfig(final Setting setting) {
|
||||||
|
// 基本信息
|
||||||
|
final String url = setting.getAndRemove(DSKeys.KEY_ALIAS_URL);
|
||||||
|
if (StrUtil.isBlank(url)) {
|
||||||
|
throw new DbRuntimeException("No JDBC URL!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除用户可能误加入的show sql配置项
|
||||||
|
// issue#I3VW0R@Gitee
|
||||||
|
removeShowSqlParams(setting);
|
||||||
|
|
||||||
|
// 自动识别Driver
|
||||||
|
String driver = setting.getAndRemove(DSKeys.KEY_ALIAS_DRIVER);
|
||||||
|
if (StrUtil.isBlank(driver)) {
|
||||||
|
driver = DriverUtil.identifyDriver(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
final DbConfig dbConfig = DbConfig.of()
|
||||||
|
.setUrl(url)
|
||||||
|
.setDriver(driver)
|
||||||
|
.setUser(setting.getAndRemove(DSKeys.KEY_ALIAS_USER))
|
||||||
|
.setPass(setting.getAndRemove(DSKeys.KEY_ALIAS_PASSWORD));
|
||||||
|
|
||||||
|
// remarks等连接配置,since 5.3.8
|
||||||
|
String connValue;
|
||||||
|
for (final String key : DSKeys.KEY_CONN_PROPS) {
|
||||||
|
connValue = setting.getAndRemove(key);
|
||||||
|
if (StrUtil.isNotBlank(connValue)) {
|
||||||
|
dbConfig.addConnProps(key, connValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义连接属性
|
||||||
|
final Props connProps = new Props();
|
||||||
|
final Set<String> keys = setting.keySet();
|
||||||
|
for (final String key : keys) {
|
||||||
|
if (key.startsWith(CONNECTION_PREFIX)) {
|
||||||
|
connProps.set(StrUtil.subSuf(key, CONNECTION_PREFIX.length()), setting.remove(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbConfig.setConnProps(connProps);
|
||||||
|
|
||||||
|
// 池属性
|
||||||
|
dbConfig.setPoolProps(setting.toProps());
|
||||||
|
|
||||||
|
return dbConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除配置文件中的Show SQL相关配置项<br>
|
||||||
|
* 此方法用于移除用户配置在分组下的配置项目
|
||||||
|
*
|
||||||
|
* @param setting 配置项
|
||||||
|
* @since 5.7.2
|
||||||
|
*/
|
||||||
|
private static void removeShowSqlParams(final Setting setting) {
|
||||||
|
setting.remove(DSKeys.KEY_SHOW_SQL);
|
||||||
|
setting.remove(DSKeys.KEY_FORMAT_SQL);
|
||||||
|
setting.remove(DSKeys.KEY_SHOW_PARAMS);
|
||||||
|
setting.remove(DSKeys.KEY_SQL_LEVEL);
|
||||||
|
}
|
||||||
|
}
|
@ -12,19 +12,15 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.db.ds;
|
package org.dromara.hutool.db.ds;
|
||||||
|
|
||||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
|
||||||
import org.dromara.hutool.core.spi.ListServiceLoader;
|
|
||||||
import org.dromara.hutool.db.DbRuntimeException;
|
import org.dromara.hutool.db.DbRuntimeException;
|
||||||
import org.dromara.hutool.db.GlobalDbConfig;
|
|
||||||
import org.dromara.hutool.log.LogUtil;
|
import org.dromara.hutool.log.LogUtil;
|
||||||
import org.dromara.hutool.setting.Setting;
|
|
||||||
|
|
||||||
import javax.naming.InitialContext;
|
import javax.naming.InitialContext;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link DataSource}和{@link DSFactory}相关工具类<br>
|
* {@link DataSource}相关工具类<br>
|
||||||
* 主要提供数据源工厂的创建和数据源的获取
|
* 主要提供数据源工厂的创建和数据源的获取
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
@ -78,7 +74,7 @@ public class DSUtil {
|
|||||||
* @return 数据源
|
* @return 数据源
|
||||||
*/
|
*/
|
||||||
public static DataSource getDS(final String group) {
|
public static DataSource getDS(final String group) {
|
||||||
return GlobalDSFactory.get().getDataSource(group);
|
return DSPool.getInstance().getDataSource(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,47 +91,7 @@ public class DSUtil {
|
|||||||
* @return 自定义的数据源工厂
|
* @return 自定义的数据源工厂
|
||||||
*/
|
*/
|
||||||
public static DSFactory setGlobalDSFactory(final DSFactory dsFactory) {
|
public static DSFactory setGlobalDSFactory(final DSFactory dsFactory) {
|
||||||
return GlobalDSFactory.set(dsFactory);
|
DSPool.getInstance().setFactory(dsFactory);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建数据源实现工厂<br>
|
|
||||||
* 此方法通过“试错”方式查找引入项目的连接池库,按照优先级寻找,一旦寻找到则创建对应的数据源工厂<br>
|
|
||||||
* 连接池优先级:Hikari > Druid > Tomcat > Dbcp > C3p0 > Hutool Pooled
|
|
||||||
*
|
|
||||||
* @param setting 数据库配置项
|
|
||||||
* @return 日志实现类
|
|
||||||
*/
|
|
||||||
public static DSFactory createFactory(final Setting setting) {
|
|
||||||
final DSFactory dsFactory = _createFactory(setting);
|
|
||||||
LogUtil.debug("Use [{}] DataSource As Default.", dsFactory.getDataSourceName());
|
|
||||||
return dsFactory;
|
return dsFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建数据源实现工厂<br>
|
|
||||||
* 此方法通过“试错”方式查找引入项目的连接池库,按照优先级寻找,一旦寻找到则创建对应的数据源工厂<br>
|
|
||||||
* 连接池优先级:Hikari > Druid > Tomcat > BeeCP > Dbcp > C3p0 > Hutool Pooled<br>
|
|
||||||
* 见:META-INF/services/org.dromara.hutool.db.ds.DSFactory
|
|
||||||
*
|
|
||||||
* @param setting 数据库配置项
|
|
||||||
* @return 日志实现类
|
|
||||||
* @since 4.1.3
|
|
||||||
*/
|
|
||||||
private static DSFactory _createFactory(Setting setting) {
|
|
||||||
if (null == setting) {
|
|
||||||
setting = GlobalDbConfig.createDbSetting();
|
|
||||||
}
|
|
||||||
final ListServiceLoader<DSFactory> loader = ListServiceLoader.of(DSFactory.class);
|
|
||||||
final int size = loader.size();
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
try {
|
|
||||||
return ConstructorUtil.newInstance(loader.getServiceClass(i), setting);
|
|
||||||
} catch (final NoClassDefFoundError | NoSuchMethodError e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new DbRuntimeException("No DSFactory implement available!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
238
hutool-db/src/main/java/org/dromara/hutool/db/ds/DbConfig.java
Normal file
238
hutool-db/src/main/java/org/dromara/hutool/db/ds/DbConfig.java
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||||
|
* Hutool is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
* https://license.coscl.org.cn/MulanPSL2
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.db.ds;
|
||||||
|
|
||||||
|
import org.dromara.hutool.db.DbRuntimeException;
|
||||||
|
import org.dromara.hutool.db.driver.DriverUtil;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库配置,包括:
|
||||||
|
* <ul>
|
||||||
|
* <li>基本配置项,如driver、url、user、password等</li>
|
||||||
|
* <li>连接配置,如remarks、useInformationSchema等</li>
|
||||||
|
* <li>连接池配置,如初始容量、最大容量等,取决于连接池库具体要求</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Looly
|
||||||
|
*/
|
||||||
|
public class DbConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建DbConfig
|
||||||
|
*
|
||||||
|
* @return DbConfig
|
||||||
|
*/
|
||||||
|
public static DbConfig of() {
|
||||||
|
return new DbConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String driver; //数据库驱动
|
||||||
|
private String url; //jdbc url
|
||||||
|
private String user; //用户名
|
||||||
|
private String pass; //密码
|
||||||
|
|
||||||
|
// 连接配置
|
||||||
|
private Properties connProps;
|
||||||
|
// 连接池配置
|
||||||
|
private Properties poolProps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*/
|
||||||
|
public DbConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param url jdbc url
|
||||||
|
* @param user 用户名
|
||||||
|
* @param pass 密码
|
||||||
|
*/
|
||||||
|
public DbConfig(final String url, final String user, final String pass) {
|
||||||
|
init(url, user, pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
*
|
||||||
|
* @param url jdbc url
|
||||||
|
* @param user 用户名
|
||||||
|
* @param pass 密码
|
||||||
|
*/
|
||||||
|
public void init(final String url, final String user, final String pass) {
|
||||||
|
this.url = url;
|
||||||
|
this.user = user;
|
||||||
|
this.pass = pass;
|
||||||
|
this.driver = DriverUtil.identifyDriver(url);
|
||||||
|
try {
|
||||||
|
Class.forName(this.driver);
|
||||||
|
} catch (final ClassNotFoundException e) {
|
||||||
|
throw new DbRuntimeException(e, "Get jdbc driver from [{}] error!", url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取JDBC驱动
|
||||||
|
*
|
||||||
|
* @return JDBC驱动
|
||||||
|
*/
|
||||||
|
public String getDriver() {
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置JDBC驱动
|
||||||
|
*
|
||||||
|
* @param driver JDBC驱动
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public DbConfig setDriver(final String driver) {
|
||||||
|
this.driver = driver;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取JDBC URL
|
||||||
|
*
|
||||||
|
* @return JDBC URL
|
||||||
|
*/
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置JDBC URL
|
||||||
|
*
|
||||||
|
* @param url JDBC URL
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public DbConfig setUrl(final String url) {
|
||||||
|
this.url = url;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户名
|
||||||
|
*
|
||||||
|
* @return 用户名
|
||||||
|
*/
|
||||||
|
public String getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置用户名
|
||||||
|
*
|
||||||
|
* @param user 用户名
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public DbConfig setUser(final String user) {
|
||||||
|
this.user = user;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取密码
|
||||||
|
*
|
||||||
|
* @return 密码
|
||||||
|
*/
|
||||||
|
public String getPass() {
|
||||||
|
return pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置密码
|
||||||
|
*
|
||||||
|
* @param pass 密码
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public DbConfig setPass(final String pass) {
|
||||||
|
this.pass = pass;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取连接属性
|
||||||
|
*
|
||||||
|
* @return 连接属性
|
||||||
|
*/
|
||||||
|
public Properties getConnProps() {
|
||||||
|
return connProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置连接属性
|
||||||
|
*
|
||||||
|
* @param connProps 连接属性
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public DbConfig setConnProps(final Properties connProps) {
|
||||||
|
this.connProps = connProps;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加连接属性
|
||||||
|
*
|
||||||
|
* @param key 属性名
|
||||||
|
* @param value 属性值
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public DbConfig addConnProps(final String key, final String value) {
|
||||||
|
if (null == this.connProps) {
|
||||||
|
this.connProps = new Properties();
|
||||||
|
}
|
||||||
|
this.connProps.setProperty(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取连接池属性
|
||||||
|
*
|
||||||
|
* @return 连接池属性
|
||||||
|
*/
|
||||||
|
public Properties getPoolProps() {
|
||||||
|
return poolProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置连接池属性
|
||||||
|
*
|
||||||
|
* @param poolProps 连接池属性
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public DbConfig setPoolProps(final Properties poolProps) {
|
||||||
|
this.poolProps = poolProps;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加连接池属性
|
||||||
|
*
|
||||||
|
* @param key 属性名
|
||||||
|
* @param value 属性值
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public DbConfig addPoolProps(final String key, final String value) {
|
||||||
|
if (null == this.poolProps) {
|
||||||
|
this.poolProps = new Properties();
|
||||||
|
}
|
||||||
|
this.poolProps.setProperty(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
|
||||||
* Hutool is licensed under Mulan PSL v2.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
|
||||||
* https://license.coscl.org.cn/MulanPSL2
|
|
||||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
||||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
||||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the Mulan PSL v2 for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.dromara.hutool.db.ds;
|
|
||||||
|
|
||||||
import org.dromara.hutool.core.io.IoUtil;
|
|
||||||
import org.dromara.hutool.core.util.RuntimeUtil;
|
|
||||||
import org.dromara.hutool.log.LogUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 全局单例数据源工厂<br>
|
|
||||||
* 一般情况下,一个应用默认只使用一种数据库连接池,因此维护一个全局的数据源工厂类减少判断连接池类型造成的性能浪费
|
|
||||||
*
|
|
||||||
* @author looly
|
|
||||||
* @since 4.0.2
|
|
||||||
*/
|
|
||||||
public class GlobalDSFactory {
|
|
||||||
|
|
||||||
private static volatile DSFactory factory;
|
|
||||||
private static final Object lock = new Object();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 设置在JVM关闭时关闭所有数据库连接
|
|
||||||
*/
|
|
||||||
static {
|
|
||||||
// JVM关闭时关闭所有连接池
|
|
||||||
RuntimeUtil.addShutdownHook(()->{
|
|
||||||
if (null != factory) {
|
|
||||||
IoUtil.closeQuietly(factory);
|
|
||||||
LogUtil.debug("DataSource: [{}] closed.", factory.getDataSourceName());
|
|
||||||
factory = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取默认的数据源工厂,读取默认数据库配置文件<br>
|
|
||||||
* 此处使用懒加载模式,在第一次调用此方法时才创建默认数据源工厂<br>
|
|
||||||
* 如果想自定义全局的数据源工厂,请在第一次调用此方法前调用{@link #set(DSFactory)} 方法自行定义
|
|
||||||
*
|
|
||||||
* @return 当前使用的数据源工厂
|
|
||||||
*/
|
|
||||||
public static DSFactory get() {
|
|
||||||
if (null == factory) {
|
|
||||||
synchronized (lock) {
|
|
||||||
if (null == factory) {
|
|
||||||
factory = DSUtil.createFactory(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置全局的数据源工厂<br>
|
|
||||||
* 在项目中存在多个连接池库的情况下,我们希望使用低优先级的库时使用此方法自定义之<br>
|
|
||||||
* 重新定义全局的数据源工厂此方法可在以下两种情况下调用:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* 1. 在get方法调用前调用此方法来自定义全局的数据源工厂
|
|
||||||
* 2. 替换已存在的全局数据源工厂,当已存在时会自动关闭
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param customDSFactory 自定义数据源工厂
|
|
||||||
* @return 自定义的数据源工厂
|
|
||||||
*/
|
|
||||||
public static DSFactory set(final DSFactory customDSFactory) {
|
|
||||||
synchronized (lock) {
|
|
||||||
if (null != factory) {
|
|
||||||
if (factory.equals(customDSFactory)) {
|
|
||||||
return factory;// 数据源工厂不变时返回原数据源工厂
|
|
||||||
}
|
|
||||||
// 自定义数据源工厂前关闭之前的数据源
|
|
||||||
IoUtil.closeQuietly(factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogUtil.debug("Custom use [{}] DataSource.", customDSFactory.getDataSourceName());
|
|
||||||
factory = customDSFactory;
|
|
||||||
}
|
|
||||||
return factory;
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,55 +14,39 @@ package org.dromara.hutool.db.ds.bee;
|
|||||||
|
|
||||||
import cn.beecp.BeeDataSource;
|
import cn.beecp.BeeDataSource;
|
||||||
import cn.beecp.BeeDataSourceConfig;
|
import cn.beecp.BeeDataSourceConfig;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
import org.dromara.hutool.db.ds.AbstractDSFactory;
|
import org.dromara.hutool.db.ds.DSFactory;
|
||||||
import org.dromara.hutool.db.ds.DSKeys;
|
import org.dromara.hutool.db.ds.DbConfig;
|
||||||
import org.dromara.hutool.setting.Setting;
|
import org.dromara.hutool.setting.props.Props;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BeeCP数据源工厂类
|
* BeeCP数据源工厂类
|
||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class BeeDSFactory extends AbstractDSFactory {
|
public class BeeDSFactory implements DSFactory {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 连接池名称:BeeCP
|
public String getDataSourceName() {
|
||||||
*/
|
return "BeeCP";
|
||||||
public static final String DS_NAME = "BeeCP";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用默认配置文件
|
|
||||||
*/
|
|
||||||
public BeeDSFactory() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用自定义配置文件
|
|
||||||
*
|
|
||||||
* @param setting 配置文件
|
|
||||||
*/
|
|
||||||
public BeeDSFactory(final Setting setting) {
|
|
||||||
super(DS_NAME, BeeDataSource.class, setting);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataSource createDataSource(final String jdbcUrl, final String driver, final String user, final String pass, final Setting poolSetting) {
|
public DataSource createDataSource(final DbConfig config) {
|
||||||
|
final BeeDataSourceConfig beeConfig = new BeeDataSourceConfig(
|
||||||
|
config.getDriver(), config.getUrl(), config.getUser(), config.getPass());
|
||||||
|
|
||||||
final BeeDataSourceConfig beeConfig = new BeeDataSourceConfig(driver, jdbcUrl, user, pass);
|
// 连接池和其它选项
|
||||||
poolSetting.toBean(beeConfig);
|
Props.of(config.getPoolProps()).toBean(beeConfig);
|
||||||
|
|
||||||
// remarks等特殊配置,since 5.3.8
|
// 连接配置
|
||||||
String connValue;
|
final Properties connProps = config.getConnProps();
|
||||||
for (final String key : DSKeys.KEY_CONN_PROPS) {
|
if(MapUtil.isNotEmpty(connProps)){
|
||||||
connValue = poolSetting.getAndRemove(key);
|
connProps.forEach((key, value)->beeConfig.addConnectProperty(key.toString(), value));
|
||||||
if (StrUtil.isNotBlank(connValue)) {
|
|
||||||
beeConfig.addConnectProperty(key, connValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BeeDataSource(beeConfig);
|
return new BeeDataSource(beeConfig);
|
||||||
|
@ -12,17 +12,16 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.db.ds.c3p0;
|
package org.dromara.hutool.db.ds.c3p0;
|
||||||
|
|
||||||
import org.dromara.hutool.core.map.MapUtil;
|
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
|
||||||
import org.dromara.hutool.db.DbRuntimeException;
|
|
||||||
import org.dromara.hutool.db.ds.AbstractDSFactory;
|
|
||||||
import org.dromara.hutool.db.ds.DSKeys;
|
|
||||||
import org.dromara.hutool.setting.Setting;
|
|
||||||
import org.dromara.hutool.setting.props.Props;
|
|
||||||
import com.mchange.v2.c3p0.ComboPooledDataSource;
|
import com.mchange.v2.c3p0.ComboPooledDataSource;
|
||||||
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
|
import org.dromara.hutool.db.DbRuntimeException;
|
||||||
|
import org.dromara.hutool.db.ds.DSFactory;
|
||||||
|
import org.dromara.hutool.db.ds.DbConfig;
|
||||||
|
import org.dromara.hutool.setting.props.Props;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import java.beans.PropertyVetoException;
|
import java.beans.PropertyVetoException;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C3P0数据源工厂类
|
* C3P0数据源工厂类
|
||||||
@ -30,59 +29,36 @@ import java.beans.PropertyVetoException;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class C3p0DSFactory extends AbstractDSFactory {
|
public class C3p0DSFactory implements DSFactory {
|
||||||
private static final long serialVersionUID = -6090788225842047281L;
|
private static final long serialVersionUID = -6090788225842047281L;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 数据源名称:C3P0
|
public String getDataSourceName() {
|
||||||
*/
|
return "C3P0";
|
||||||
public static final String DS_NAME = "C3P0";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用默认配置
|
|
||||||
*/
|
|
||||||
public C3p0DSFactory() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用自定义配置文件
|
|
||||||
*
|
|
||||||
* @param setting 配置
|
|
||||||
*/
|
|
||||||
public C3p0DSFactory(final Setting setting) {
|
|
||||||
super(DS_NAME, ComboPooledDataSource.class, setting);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataSource createDataSource(final String jdbcUrl, final String driver, final String user, final String pass, final Setting poolSetting) {
|
public DataSource createDataSource(final DbConfig config) {
|
||||||
final ComboPooledDataSource ds = new ComboPooledDataSource();
|
final ComboPooledDataSource ds = new ComboPooledDataSource();
|
||||||
|
|
||||||
// remarks等特殊配置,since 5.3.8
|
ds.setJdbcUrl(config.getUrl());
|
||||||
final Props connProps = new Props();
|
try {
|
||||||
String connValue;
|
ds.setDriverClass(config.getDriver());
|
||||||
for (final String key : DSKeys.KEY_CONN_PROPS) {
|
} catch (final PropertyVetoException e) {
|
||||||
connValue = poolSetting.getAndRemove(key);
|
throw new DbRuntimeException(e);
|
||||||
if(StrUtil.isNotBlank(connValue)){
|
|
||||||
connProps.setProperty(key, connValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ds.setUser(config.getUser());
|
||||||
|
ds.setPassword(config.getPass());
|
||||||
|
|
||||||
|
// 连接池和其它选项
|
||||||
|
Props.of(config.getPoolProps()).toBean(ds);
|
||||||
|
|
||||||
|
// 连接配置
|
||||||
|
final Properties connProps = config.getConnProps();
|
||||||
if(MapUtil.isNotEmpty(connProps)){
|
if(MapUtil.isNotEmpty(connProps)){
|
||||||
ds.setProperties(connProps);
|
ds.setProperties(connProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
ds.setJdbcUrl(jdbcUrl);
|
|
||||||
try {
|
|
||||||
ds.setDriverClass(driver);
|
|
||||||
} catch (final PropertyVetoException e) {
|
|
||||||
throw new DbRuntimeException(e);
|
|
||||||
}
|
|
||||||
ds.setUser(user);
|
|
||||||
ds.setPassword(pass);
|
|
||||||
|
|
||||||
// 注入属性
|
|
||||||
poolSetting.toBean(ds);
|
|
||||||
|
|
||||||
return ds;
|
return ds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,14 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.db.ds.dbcp;
|
package org.dromara.hutool.db.ds.dbcp;
|
||||||
|
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
|
||||||
import org.dromara.hutool.db.ds.AbstractDSFactory;
|
|
||||||
import org.dromara.hutool.db.ds.DSKeys;
|
|
||||||
import org.dromara.hutool.setting.Setting;
|
|
||||||
import org.apache.commons.dbcp2.BasicDataSource;
|
import org.apache.commons.dbcp2.BasicDataSource;
|
||||||
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
|
import org.dromara.hutool.db.ds.DSFactory;
|
||||||
|
import org.dromara.hutool.db.ds.DbConfig;
|
||||||
|
import org.dromara.hutool.setting.props.Props;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DBCP2数据源工厂类
|
* DBCP2数据源工厂类
|
||||||
@ -26,50 +27,31 @@ import javax.sql.DataSource;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DbcpDSFactory extends AbstractDSFactory {
|
public class DbcpDSFactory implements DSFactory {
|
||||||
private static final long serialVersionUID = -9133501414334104548L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 数据源名称:commons-dbcp2
|
public String getDataSourceName() {
|
||||||
*/
|
return "commons-dbcp2";
|
||||||
public static final String DS_NAME = "commons-dbcp2";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用默认配置文件
|
|
||||||
*/
|
|
||||||
public DbcpDSFactory() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用自定义配置文件
|
|
||||||
*
|
|
||||||
* @param setting 配置
|
|
||||||
*/
|
|
||||||
public DbcpDSFactory(final Setting setting) {
|
|
||||||
super(DS_NAME, BasicDataSource.class, setting);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataSource createDataSource(final String jdbcUrl, final String driver, final String user, final String pass, final Setting poolSetting) {
|
public DataSource createDataSource(final DbConfig config) {
|
||||||
final BasicDataSource ds = new BasicDataSource();
|
final BasicDataSource ds = new BasicDataSource();
|
||||||
|
|
||||||
ds.setUrl(jdbcUrl);
|
ds.setUrl(config.getUrl());
|
||||||
ds.setDriverClassName(driver);
|
ds.setDriverClassName(config.getDriver());
|
||||||
ds.setUsername(user);
|
ds.setUsername(config.getUser());
|
||||||
ds.setPassword(pass);
|
ds.setPassword(config.getPass());
|
||||||
|
|
||||||
// remarks等特殊配置,since 5.3.8
|
// 连接池和其它选项
|
||||||
String connValue;
|
Props.of(config.getPoolProps()).toBean(ds);
|
||||||
for (final String key : DSKeys.KEY_CONN_PROPS) {
|
|
||||||
connValue = poolSetting.getAndRemove(key);
|
|
||||||
if(StrUtil.isNotBlank(connValue)){
|
|
||||||
ds.addConnectionProperty(key, connValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 注入属性
|
// 连接配置
|
||||||
poolSetting.toBean(ds);
|
final Properties connProps = config.getConnProps();
|
||||||
|
if(MapUtil.isNotEmpty(connProps)){
|
||||||
|
connProps.forEach((key, value)->ds.addConnectionProperty(key.toString(), value.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
return ds;
|
return ds;
|
||||||
}
|
}
|
||||||
|
@ -12,14 +12,15 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.db.ds.druid;
|
package org.dromara.hutool.db.ds.druid;
|
||||||
|
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
|
||||||
import org.dromara.hutool.db.ds.AbstractDSFactory;
|
|
||||||
import org.dromara.hutool.db.ds.DSKeys;
|
|
||||||
import org.dromara.hutool.setting.Setting;
|
|
||||||
import org.dromara.hutool.setting.props.Props;
|
|
||||||
import com.alibaba.druid.pool.DruidDataSource;
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
import org.dromara.hutool.db.ds.DSFactory;
|
||||||
|
import org.dromara.hutool.db.ds.DbConfig;
|
||||||
|
import org.dromara.hutool.setting.props.Props;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Druid数据源工厂类
|
* Druid数据源工厂类
|
||||||
@ -27,53 +28,33 @@ import javax.sql.DataSource;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DruidDSFactory extends AbstractDSFactory {
|
public class DruidDSFactory implements DSFactory {
|
||||||
private static final long serialVersionUID = 4680621702534433222L;
|
private static final long serialVersionUID = 4680621702534433222L;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 数据源名称:Druid
|
public String getDataSourceName() {
|
||||||
*/
|
return "Druid";
|
||||||
public static final String DS_NAME = "Druid";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用默认配置文件
|
|
||||||
*/
|
|
||||||
public DruidDSFactory() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用自定义配置文件
|
|
||||||
*
|
|
||||||
* @param setting 配置
|
|
||||||
*/
|
|
||||||
public DruidDSFactory(final Setting setting) {
|
|
||||||
super(DS_NAME, DruidDataSource.class, setting);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataSource createDataSource(final String jdbcUrl, final String driver, final String user, final String pass, final Setting poolSetting) {
|
public DataSource createDataSource(final DbConfig config) {
|
||||||
final DruidDataSource ds = new DruidDataSource();
|
final DruidDataSource ds = new DruidDataSource();
|
||||||
|
|
||||||
// 基本信息
|
// 基本信息
|
||||||
ds.setUrl(jdbcUrl);
|
ds.setUrl(config.getUrl());
|
||||||
ds.setDriverClassName(driver);
|
ds.setDriverClassName(config.getDriver());
|
||||||
ds.setUsername(user);
|
ds.setUsername(config.getUser());
|
||||||
ds.setPassword(pass);
|
ds.setPassword(config.getPass());
|
||||||
|
|
||||||
// remarks等特殊配置,since 5.3.8
|
// 连接配置
|
||||||
// Druid中也可以通过 druid.connectProperties 属性设置
|
final Properties connProps = config.getConnProps();
|
||||||
String connValue;
|
if(MapUtil.isNotEmpty(connProps)){
|
||||||
for (final String key : DSKeys.KEY_CONN_PROPS) {
|
connProps.forEach((key, value)->ds.addConnectionProperty(key.toString(), value.toString()));
|
||||||
connValue = poolSetting.getAndRemove(key);
|
|
||||||
if(StrUtil.isNotBlank(connValue)){
|
|
||||||
ds.addConnectionProperty(key, connValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Druid连接池配置信息,规范化属性名
|
// Druid连接池配置信息,规范化属性名
|
||||||
final Props druidProps = new Props();
|
final Props druidProps = new Props();
|
||||||
poolSetting.forEach((key, value)-> druidProps.put(StrUtil.addPrefixIfNot(key, "druid."), value));
|
config.getPoolProps().forEach((key, value)-> druidProps.set(StrUtil.addPrefixIfNot(key.toString(), "druid."), value));
|
||||||
ds.configFromPropeties(druidProps);
|
ds.configFromPropeties(druidProps);
|
||||||
|
|
||||||
//issue#I4ZKCW 某些非属性设置单独设置
|
//issue#I4ZKCW 某些非属性设置单独设置
|
||||||
|
@ -12,13 +12,11 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.db.ds.hikari;
|
package org.dromara.hutool.db.ds.hikari;
|
||||||
|
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
|
||||||
import org.dromara.hutool.db.ds.AbstractDSFactory;
|
|
||||||
import org.dromara.hutool.db.ds.DSKeys;
|
|
||||||
import org.dromara.hutool.setting.Setting;
|
|
||||||
import org.dromara.hutool.setting.props.Props;
|
|
||||||
import com.zaxxer.hikari.HikariConfig;
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import org.dromara.hutool.db.ds.DSFactory;
|
||||||
|
import org.dromara.hutool.db.ds.DbConfig;
|
||||||
|
import org.dromara.hutool.setting.props.Props;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
@ -28,59 +26,41 @@ import javax.sql.DataSource;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class HikariDSFactory extends AbstractDSFactory {
|
public class HikariDSFactory implements DSFactory {
|
||||||
private static final long serialVersionUID = -8834744983614749401L;
|
private static final long serialVersionUID = -8834744983614749401L;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 数据源名称:HikariCP
|
public String getDataSourceName() {
|
||||||
*/
|
return "HikariCP";
|
||||||
public static final String DS_NAME = "HikariCP";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用默认配置文件
|
|
||||||
*/
|
|
||||||
public HikariDSFactory() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用自定义配置文件
|
|
||||||
*
|
|
||||||
* @param setting 配置
|
|
||||||
*/
|
|
||||||
public HikariDSFactory(final Setting setting) {
|
|
||||||
super(DS_NAME, HikariDataSource.class, setting);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataSource createDataSource(final String jdbcUrl, final String driver, final String user, final String pass, final Setting poolSetting) {
|
public DataSource createDataSource(final DbConfig config) {
|
||||||
// remarks等特殊配置,since 5.3.8
|
final Props props = new Props();
|
||||||
final Props connProps = new Props();
|
|
||||||
String connValue;
|
|
||||||
for (final String key : DSKeys.KEY_CONN_PROPS) {
|
|
||||||
connValue = poolSetting.getAndRemove(key);
|
|
||||||
if(StrUtil.isNotBlank(connValue)){
|
|
||||||
connProps.setProperty(key, connValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final Props config = new Props();
|
// 基本信息
|
||||||
config.putAll(poolSetting);
|
props.put("jdbcUrl", config.getUrl());
|
||||||
|
final String driver = config.getDriver();
|
||||||
config.put("jdbcUrl", jdbcUrl);
|
|
||||||
if (null != driver) {
|
if (null != driver) {
|
||||||
config.put("driverClassName", driver);
|
props.put("driverClassName", driver);
|
||||||
}
|
}
|
||||||
|
final String user = config.getUser();
|
||||||
if (null != user) {
|
if (null != user) {
|
||||||
config.put("username", user);
|
props.put("username", user);
|
||||||
}
|
}
|
||||||
|
final String pass = config.getPass();
|
||||||
if (null != pass) {
|
if (null != pass) {
|
||||||
config.put("password", pass);
|
props.put("password", pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
final HikariConfig hikariConfig = new HikariConfig(config);
|
// 连接池信息
|
||||||
hikariConfig.setDataSourceProperties(connProps);
|
props.putAll(config.getPoolProps());
|
||||||
|
|
||||||
|
final HikariConfig hikariConfig = new HikariConfig(props);
|
||||||
|
// 连接信息
|
||||||
|
hikariConfig.setDataSourceProperties(config.getConnProps());
|
||||||
|
|
||||||
return new HikariDataSource(hikariConfig);
|
return new HikariDataSource(hikariConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ package org.dromara.hutool.db.ds.jndi;
|
|||||||
|
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
import org.dromara.hutool.db.DbRuntimeException;
|
import org.dromara.hutool.db.DbRuntimeException;
|
||||||
import org.dromara.hutool.db.ds.AbstractDSFactory;
|
import org.dromara.hutool.db.ds.DSFactory;
|
||||||
import org.dromara.hutool.db.ds.DSUtil;
|
import org.dromara.hutool.db.ds.DSUtil;
|
||||||
import org.dromara.hutool.setting.Setting;
|
import org.dromara.hutool.db.ds.DbConfig;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
@ -31,33 +31,17 @@ import javax.sql.DataSource;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class JndiDSFactory extends AbstractDSFactory {
|
public class JndiDSFactory implements DSFactory {
|
||||||
private static final long serialVersionUID = 1573625812927370432L;
|
private static final long serialVersionUID = 1573625812927370432L;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 数据源名称:JNDI DataSource
|
public String getDataSourceName() {
|
||||||
*/
|
return "JNDI DataSource";
|
||||||
public static final String DS_NAME = "JNDI DataSource";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用默认配置文件
|
|
||||||
*/
|
|
||||||
public JndiDSFactory() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用自定义配置文件
|
|
||||||
*
|
|
||||||
* @param setting 配置
|
|
||||||
*/
|
|
||||||
public JndiDSFactory(final Setting setting) {
|
|
||||||
super(DS_NAME, null, setting);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataSource createDataSource(final String jdbcUrl, final String driver, final String user, final String pass, final Setting poolSetting) {
|
public DataSource createDataSource(final DbConfig config) {
|
||||||
final String jndiName = poolSetting.getStr("jndi");
|
final String jndiName = config.getPoolProps().getProperty("jndi");
|
||||||
if (StrUtil.isEmpty(jndiName)) {
|
if (StrUtil.isEmpty(jndiName)) {
|
||||||
throw new DbRuntimeException("No setting name [jndi] for this group.");
|
throw new DbRuntimeException("No setting name [jndi] for this group.");
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ package org.dromara.hutool.db.ds.pooled;
|
|||||||
import org.dromara.hutool.core.map.MapUtil;
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
import org.dromara.hutool.core.pool.Poolable;
|
import org.dromara.hutool.core.pool.Poolable;
|
||||||
import org.dromara.hutool.db.DbRuntimeException;
|
import org.dromara.hutool.db.DbRuntimeException;
|
||||||
|
import org.dromara.hutool.db.ds.DbConfig;
|
||||||
import org.dromara.hutool.setting.props.Props;
|
import org.dromara.hutool.setting.props.Props;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
@ -40,7 +41,7 @@ public class PooledConnection extends ConnectionWrapper implements Poolable<Conn
|
|||||||
* @param config 数据库配置
|
* @param config 数据库配置
|
||||||
* @param dataSource 数据源
|
* @param dataSource 数据源
|
||||||
*/
|
*/
|
||||||
public PooledConnection(final PooledDbConfig config, final PooledDataSource dataSource) {
|
public PooledConnection(final DbConfig config, final PooledDataSource dataSource) {
|
||||||
final Props info = new Props();
|
final Props info = new Props();
|
||||||
final String user = config.getUser();
|
final String user = config.getUser();
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
|
@ -12,10 +12,8 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.db.ds.pooled;
|
package org.dromara.hutool.db.ds.pooled;
|
||||||
|
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.db.ds.DSFactory;
|
||||||
import org.dromara.hutool.db.ds.AbstractDSFactory;
|
import org.dromara.hutool.db.ds.DbConfig;
|
||||||
import org.dromara.hutool.db.ds.DSKeys;
|
|
||||||
import org.dromara.hutool.setting.Setting;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
@ -25,53 +23,16 @@ import javax.sql.DataSource;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class PooledDSFactory extends AbstractDSFactory {
|
public class PooledDSFactory implements DSFactory {
|
||||||
private static final long serialVersionUID = 8093886210895248277L;
|
private static final long serialVersionUID = 8093886210895248277L;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 数据源名称:Hutool-Pooled-DataSource
|
public String getDataSourceName() {
|
||||||
*/
|
return "Hutool-Pooled-DataSource";
|
||||||
public static final String DS_NAME = "Hutool-Pooled-DataSource";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用默认配置文件
|
|
||||||
*/
|
|
||||||
public PooledDSFactory() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用自定义配置文件
|
|
||||||
*
|
|
||||||
* @param setting 配置
|
|
||||||
*/
|
|
||||||
public PooledDSFactory(final Setting setting) {
|
|
||||||
super(DS_NAME, PooledDataSource.class, setting);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataSource createDataSource(final String jdbcUrl, final String driver, final String user, final String pass, final Setting poolSetting) {
|
public DataSource createDataSource(final DbConfig config) {
|
||||||
final PooledDbConfig pooledDbConfig = new PooledDbConfig();
|
return new PooledDataSource(config);
|
||||||
pooledDbConfig.setUrl(jdbcUrl);
|
|
||||||
pooledDbConfig.setDriver(driver);
|
|
||||||
pooledDbConfig.setUser(user);
|
|
||||||
pooledDbConfig.setPass(pass);
|
|
||||||
|
|
||||||
// 连接池相关信息
|
|
||||||
pooledDbConfig.setInitialSize(poolSetting.getInt("initialSize", 0));
|
|
||||||
pooledDbConfig.setMinIdle(poolSetting.getInt("minIdle", 0));
|
|
||||||
pooledDbConfig.setMaxActive(poolSetting.getInt("maxActive", 8));
|
|
||||||
pooledDbConfig.setMaxWait(poolSetting.getLong("maxWait", 6000L));
|
|
||||||
|
|
||||||
// remarks等特殊配置,since 5.3.8
|
|
||||||
String connValue;
|
|
||||||
for (final String key : DSKeys.KEY_CONN_PROPS) {
|
|
||||||
connValue = poolSetting.get(key);
|
|
||||||
if(StrUtil.isNotBlank(connValue)){
|
|
||||||
pooledDbConfig.addConnProps(key, connValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PooledDataSource(pooledDbConfig);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,9 @@ import org.dromara.hutool.core.pool.ObjectPool;
|
|||||||
import org.dromara.hutool.core.pool.partition.PartitionObjectPool;
|
import org.dromara.hutool.core.pool.partition.PartitionObjectPool;
|
||||||
import org.dromara.hutool.core.pool.partition.PartitionPoolConfig;
|
import org.dromara.hutool.core.pool.partition.PartitionPoolConfig;
|
||||||
import org.dromara.hutool.db.DbRuntimeException;
|
import org.dromara.hutool.db.DbRuntimeException;
|
||||||
|
import org.dromara.hutool.db.ds.DbConfig;
|
||||||
import org.dromara.hutool.db.ds.simple.AbstractDataSource;
|
import org.dromara.hutool.db.ds.simple.AbstractDataSource;
|
||||||
|
import org.dromara.hutool.setting.props.Props;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@ -31,6 +33,11 @@ import java.sql.SQLException;
|
|||||||
*/
|
*/
|
||||||
public class PooledDataSource extends AbstractDataSource {
|
public class PooledDataSource extends AbstractDataSource {
|
||||||
|
|
||||||
|
private static final String KEY_MAX_WAIT = "maxWait";
|
||||||
|
private static final String KEY_INITIAL_SIZE = "initialSize";
|
||||||
|
private static final String KEY_MAX_ACTIVE = "maxActive";
|
||||||
|
|
||||||
|
private final int maxWait;
|
||||||
private final ObjectPool<Connection> connPool;
|
private final ObjectPool<Connection> connPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,12 +45,16 @@ public class PooledDataSource extends AbstractDataSource {
|
|||||||
*
|
*
|
||||||
* @param config 数据库池配置
|
* @param config 数据库池配置
|
||||||
*/
|
*/
|
||||||
public PooledDataSource(final PooledDbConfig config) {
|
public PooledDataSource(final DbConfig config) {
|
||||||
|
|
||||||
|
final Props poolProps = Props.of(config.getPoolProps());
|
||||||
|
this.maxWait = poolProps.getInt(KEY_MAX_WAIT, 6000);
|
||||||
|
|
||||||
final PartitionPoolConfig poolConfig = (PartitionPoolConfig) PartitionPoolConfig.of()
|
final PartitionPoolConfig poolConfig = (PartitionPoolConfig) PartitionPoolConfig.of()
|
||||||
.setPartitionSize(1)
|
.setPartitionSize(1)
|
||||||
.setMaxWait(config.getMaxWait())
|
.setMaxWait(this.maxWait)
|
||||||
.setMinSize(config.getInitialSize())
|
.setMinSize(poolProps.getInt(KEY_INITIAL_SIZE, 0))
|
||||||
.setMaxSize(config.getMaxActive());
|
.setMaxSize(poolProps.getInt(KEY_MAX_ACTIVE, 8));
|
||||||
|
|
||||||
this.connPool = new PartitionObjectPool<>(poolConfig, createConnFactory(config));
|
this.connPool = new PartitionObjectPool<>(poolConfig, createConnFactory(config));
|
||||||
}
|
}
|
||||||
@ -78,7 +89,7 @@ public class PooledDataSource extends AbstractDataSource {
|
|||||||
* @param config 数据库配置
|
* @param config 数据库配置
|
||||||
* @return {@link ObjectFactory}
|
* @return {@link ObjectFactory}
|
||||||
*/
|
*/
|
||||||
private ObjectFactory<Connection> createConnFactory(final PooledDbConfig config) {
|
private ObjectFactory<Connection> createConnFactory(final DbConfig config) {
|
||||||
return new ObjectFactory<Connection>() {
|
return new ObjectFactory<Connection>() {
|
||||||
@Override
|
@Override
|
||||||
public Connection create() {
|
public Connection create() {
|
||||||
@ -88,7 +99,8 @@ public class PooledDataSource extends AbstractDataSource {
|
|||||||
@Override
|
@Override
|
||||||
public boolean validate(final Connection connection) {
|
public boolean validate(final Connection connection) {
|
||||||
try {
|
try {
|
||||||
return null != connection && connection.isValid((int) config.getMaxWait());
|
return null != connection
|
||||||
|
&& connection.isValid(maxWait);
|
||||||
} catch (final SQLException e) {
|
} catch (final SQLException e) {
|
||||||
throw new DbRuntimeException(e);
|
throw new DbRuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
|
||||||
* Hutool is licensed under Mulan PSL v2.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
|
||||||
* https://license.coscl.org.cn/MulanPSL2
|
|
||||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
||||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
||||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the Mulan PSL v2 for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.dromara.hutool.db.ds.pooled;
|
|
||||||
|
|
||||||
import org.dromara.hutool.db.ds.simple.DbConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据库配置
|
|
||||||
*
|
|
||||||
* @author Looly
|
|
||||||
*/
|
|
||||||
public class PooledDbConfig extends DbConfig {
|
|
||||||
|
|
||||||
private int initialSize; //初始连接数
|
|
||||||
private int minIdle; //最小闲置连接数
|
|
||||||
private int maxActive; //最大活跃连接数
|
|
||||||
private long maxWait; //连接的超时等待
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造
|
|
||||||
*/
|
|
||||||
public PooledDbConfig() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造
|
|
||||||
*
|
|
||||||
* @param url jdbc url
|
|
||||||
* @param user 用户名
|
|
||||||
* @param pass 密码
|
|
||||||
*/
|
|
||||||
public PooledDbConfig(final String url, final String user, final String pass) {
|
|
||||||
super(url, user, pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取初始大小
|
|
||||||
*
|
|
||||||
* @return 初始大小
|
|
||||||
*/
|
|
||||||
public int getInitialSize() {
|
|
||||||
return initialSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置初始大小
|
|
||||||
*
|
|
||||||
* @param initialSize 初始大小
|
|
||||||
*/
|
|
||||||
public void setInitialSize(final int initialSize) {
|
|
||||||
this.initialSize = initialSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取最小闲置连接数
|
|
||||||
*
|
|
||||||
* @return 最小闲置连接数
|
|
||||||
*/
|
|
||||||
public int getMinIdle() {
|
|
||||||
return minIdle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置最小闲置连接数
|
|
||||||
*
|
|
||||||
* @param minIdle 最小闲置连接数
|
|
||||||
*/
|
|
||||||
public void setMinIdle(final int minIdle) {
|
|
||||||
this.minIdle = minIdle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取最大活跃连接数
|
|
||||||
*
|
|
||||||
* @return 最大活跃连接数
|
|
||||||
*/
|
|
||||||
public int getMaxActive() {
|
|
||||||
return maxActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置最大活跃连接数
|
|
||||||
*
|
|
||||||
* @param maxActive 最大活跃连接数
|
|
||||||
*/
|
|
||||||
public void setMaxActive(final int maxActive) {
|
|
||||||
this.maxActive = maxActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取连接的超时等待
|
|
||||||
*
|
|
||||||
* @return 连接的超时等待
|
|
||||||
*/
|
|
||||||
public long getMaxWait() {
|
|
||||||
return maxWait;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置连接的超时等待
|
|
||||||
*
|
|
||||||
* @param maxWait 连接的超时等待
|
|
||||||
*/
|
|
||||||
public void setMaxWait(final long maxWait) {
|
|
||||||
this.maxWait = maxWait;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
|
||||||
* Hutool is licensed under Mulan PSL v2.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
|
||||||
* https://license.coscl.org.cn/MulanPSL2
|
|
||||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
||||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
||||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the Mulan PSL v2 for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.dromara.hutool.db.ds.simple;
|
|
||||||
|
|
||||||
import org.dromara.hutool.db.DbRuntimeException;
|
|
||||||
import org.dromara.hutool.db.driver.DriverUtil;
|
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据库配置
|
|
||||||
*
|
|
||||||
* @author Looly
|
|
||||||
*/
|
|
||||||
public class DbConfig {
|
|
||||||
|
|
||||||
private String driver; //数据库驱动
|
|
||||||
private String url; //jdbc url
|
|
||||||
private String user; //用户名
|
|
||||||
private String pass; //密码
|
|
||||||
|
|
||||||
// 连接配置
|
|
||||||
private Properties connProps;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造
|
|
||||||
*/
|
|
||||||
public DbConfig() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造
|
|
||||||
*
|
|
||||||
* @param url jdbc url
|
|
||||||
* @param user 用户名
|
|
||||||
* @param pass 密码
|
|
||||||
*/
|
|
||||||
public DbConfig(final String url, final String user, final String pass) {
|
|
||||||
init(url, user, pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化
|
|
||||||
*
|
|
||||||
* @param url jdbc url
|
|
||||||
* @param user 用户名
|
|
||||||
* @param pass 密码
|
|
||||||
*/
|
|
||||||
public void init(final String url, final String user, final String pass) {
|
|
||||||
this.url = url;
|
|
||||||
this.user = user;
|
|
||||||
this.pass = pass;
|
|
||||||
this.driver = DriverUtil.identifyDriver(url);
|
|
||||||
try {
|
|
||||||
Class.forName(this.driver);
|
|
||||||
} catch (final ClassNotFoundException e) {
|
|
||||||
throw new DbRuntimeException(e, "Get jdbc driver from [{}] error!", url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDriver() {
|
|
||||||
return driver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDriver(final String driver) {
|
|
||||||
this.driver = driver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUrl() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUrl(final String url) {
|
|
||||||
this.url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUser() {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUser(final String user) {
|
|
||||||
this.user = user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPass() {
|
|
||||||
return pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPass(final String pass) {
|
|
||||||
this.pass = pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Properties getConnProps() {
|
|
||||||
return connProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setConnProps(final Properties connProps) {
|
|
||||||
this.connProps = connProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addConnProps(final String key, final String value){
|
|
||||||
if(null == this.connProps){
|
|
||||||
this.connProps = new Properties();
|
|
||||||
}
|
|
||||||
this.connProps.setProperty(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,8 +12,8 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.db.ds.simple;
|
package org.dromara.hutool.db.ds.simple;
|
||||||
|
|
||||||
import org.dromara.hutool.db.ds.AbstractDSFactory;
|
import org.dromara.hutool.db.ds.DSFactory;
|
||||||
import org.dromara.hutool.setting.Setting;
|
import org.dromara.hutool.db.ds.DbConfig;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
@ -23,36 +23,16 @@ import javax.sql.DataSource;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SimpleDSFactory extends AbstractDSFactory {
|
public class SimpleDSFactory implements DSFactory {
|
||||||
private static final long serialVersionUID = 4738029988261034743L;
|
private static final long serialVersionUID = 4738029988261034743L;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 数据源名称:Hutool-Simple-DataSource
|
public String getDataSourceName() {
|
||||||
*/
|
return "Hutool-Simple-DataSource";
|
||||||
public static final String DS_NAME = "Hutool-Simple-DataSource";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用默认配置文件
|
|
||||||
*/
|
|
||||||
public SimpleDSFactory() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,使用自定义配置文件
|
|
||||||
*
|
|
||||||
* @param setting 配置
|
|
||||||
*/
|
|
||||||
public SimpleDSFactory(final Setting setting) {
|
|
||||||
super(DS_NAME, SimpleDataSource.class, setting);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataSource createDataSource(final String jdbcUrl, final String driver, final String user, final String pass, final Setting poolSetting) {
|
public DataSource createDataSource(final DbConfig config) {
|
||||||
final DbConfig dbConfig = new DbConfig(jdbcUrl, user, pass);
|
return new SimpleDataSource(config);
|
||||||
dbConfig.setDriver(driver);
|
|
||||||
dbConfig.setConnProps(poolSetting.getProps(Setting.DEFAULT_GROUP));
|
|
||||||
|
|
||||||
return new SimpleDataSource(dbConfig);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
package org.dromara.hutool.db.ds.simple;
|
package org.dromara.hutool.db.ds.simple;
|
||||||
|
|
||||||
import org.dromara.hutool.core.map.MapUtil;
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
|
import org.dromara.hutool.db.ds.DbConfig;
|
||||||
import org.dromara.hutool.setting.props.Props;
|
import org.dromara.hutool.setting.props.Props;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
@ -12,65 +12,40 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.db.ds.tomcat;
|
package org.dromara.hutool.db.ds.tomcat;
|
||||||
|
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
|
||||||
import org.dromara.hutool.db.ds.AbstractDSFactory;
|
|
||||||
import org.dromara.hutool.db.ds.DSKeys;
|
|
||||||
import org.dromara.hutool.setting.Setting;
|
|
||||||
import org.dromara.hutool.setting.props.Props;
|
|
||||||
import org.apache.tomcat.jdbc.pool.DataSource;
|
import org.apache.tomcat.jdbc.pool.DataSource;
|
||||||
import org.apache.tomcat.jdbc.pool.PoolProperties;
|
import org.apache.tomcat.jdbc.pool.PoolProperties;
|
||||||
|
import org.dromara.hutool.db.ds.DSFactory;
|
||||||
|
import org.dromara.hutool.db.ds.DbConfig;
|
||||||
|
import org.dromara.hutool.setting.props.Props;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tomcat-Jdbc-Pool数据源工厂类
|
* Tomcat-Jdbc-Pool数据源工厂类
|
||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class TomcatDSFactory extends AbstractDSFactory {
|
public class TomcatDSFactory implements DSFactory {
|
||||||
private static final long serialVersionUID = 4925514193275150156L;
|
private static final long serialVersionUID = 4925514193275150156L;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 数据源名称:Tomcat-Jdbc-Pool
|
public String getDataSourceName() {
|
||||||
*/
|
return "Tomcat-Jdbc-Pool";
|
||||||
public static final String DS_NAME = "Tomcat-Jdbc-Pool";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造
|
|
||||||
*/
|
|
||||||
public TomcatDSFactory() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造,自定义配置
|
|
||||||
*
|
|
||||||
* @param setting Setting数据库配置
|
|
||||||
*/
|
|
||||||
public TomcatDSFactory(final Setting setting) {
|
|
||||||
super(DS_NAME, DataSource.class, setting);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected javax.sql.DataSource createDataSource(final String jdbcUrl, final String driver, final String user, final String pass, final Setting poolSetting) {
|
public javax.sql.DataSource createDataSource(final DbConfig config) {
|
||||||
final PoolProperties poolProps = new PoolProperties();
|
final PoolProperties poolProps = new PoolProperties();
|
||||||
poolProps.setUrl(jdbcUrl);
|
|
||||||
poolProps.setDriverClassName(driver);
|
|
||||||
poolProps.setUsername(user);
|
|
||||||
poolProps.setPassword(pass);
|
|
||||||
|
|
||||||
// remarks等特殊配置,since 5.3.8
|
// 基本配置
|
||||||
final Props connProps = new Props();
|
poolProps.setUrl(config.getUrl());
|
||||||
String connValue;
|
poolProps.setDriverClassName(config.getDriver());
|
||||||
for (final String key : DSKeys.KEY_CONN_PROPS) {
|
poolProps.setUsername(config.getUser());
|
||||||
connValue = poolSetting.getAndRemove(key);
|
poolProps.setPassword(config.getPass());
|
||||||
if(StrUtil.isNotBlank(connValue)){
|
|
||||||
connProps.setProperty(key, connValue);
|
// 连接配置
|
||||||
}
|
poolProps.setDbProperties(config.getConnProps());
|
||||||
}
|
|
||||||
poolProps.setDbProperties(connProps);
|
|
||||||
|
|
||||||
// 连接池相关参数
|
// 连接池相关参数
|
||||||
poolSetting.toBean(poolProps);
|
Props.of(config.getPoolProps()).toBean(poolProps);
|
||||||
|
|
||||||
return new DataSource(poolProps);
|
return new DataSource(poolProps);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.db.ds;
|
package org.dromara.hutool.db.ds;
|
||||||
|
|
||||||
import org.dromara.hutool.db.ds.simple.DbConfig;
|
|
||||||
import org.dromara.hutool.db.ds.simple.SimpleDataSource;
|
import org.dromara.hutool.db.ds.simple.SimpleDataSource;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -383,20 +383,20 @@ public class Setting extends AbsSetting implements Map<String, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换为Properties对象,原分组变为前缀
|
* 转换为{@link Props}对象,原分组变为前缀
|
||||||
*
|
*
|
||||||
* @return Properties对象
|
* @return {@link Props}对象
|
||||||
*/
|
*/
|
||||||
public Properties toProperties() {
|
public Props toProps() {
|
||||||
final Properties properties = new Properties();
|
final Props props = new Props();
|
||||||
String group;
|
String group;
|
||||||
for (final Entry<String, LinkedHashMap<String, String>> groupEntry : this.groupedMap.entrySet()) {
|
for (final Entry<String, LinkedHashMap<String, String>> groupEntry : this.groupedMap.entrySet()) {
|
||||||
group = groupEntry.getKey();
|
group = groupEntry.getKey();
|
||||||
for (final Entry<String, String> entry : groupEntry.getValue().entrySet()) {
|
for (final Entry<String, String> entry : groupEntry.getValue().entrySet()) {
|
||||||
properties.setProperty(StrUtil.isEmpty(group) ? entry.getKey() : group + CharUtil.DOT + entry.getKey(), entry.getValue());
|
props.setProperty(StrUtil.isEmpty(group) ? entry.getKey() : group + CharUtil.DOT + entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return properties;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,20 +13,19 @@
|
|||||||
package org.dromara.hutool.setting.props;
|
package org.dromara.hutool.setting.props;
|
||||||
|
|
||||||
import org.dromara.hutool.core.bean.BeanUtil;
|
import org.dromara.hutool.core.bean.BeanUtil;
|
||||||
import org.dromara.hutool.core.io.file.FileUtil;
|
|
||||||
import org.dromara.hutool.core.io.IORuntimeException;
|
|
||||||
import org.dromara.hutool.core.io.IoUtil;
|
|
||||||
import org.dromara.hutool.core.io.resource.Resource;
|
|
||||||
import org.dromara.hutool.core.io.resource.ResourceUtil;
|
|
||||||
import org.dromara.hutool.core.io.resource.UrlResource;
|
|
||||||
import org.dromara.hutool.core.io.watch.SimpleWatcher;
|
|
||||||
import org.dromara.hutool.core.io.watch.WatchMonitor;
|
|
||||||
import org.dromara.hutool.core.io.watch.WatchUtil;
|
|
||||||
import org.dromara.hutool.core.lang.Assert;
|
|
||||||
import org.dromara.hutool.core.func.LambdaInfo;
|
import org.dromara.hutool.core.func.LambdaInfo;
|
||||||
import org.dromara.hutool.core.func.LambdaUtil;
|
import org.dromara.hutool.core.func.LambdaUtil;
|
||||||
import org.dromara.hutool.core.func.SerFunction;
|
import org.dromara.hutool.core.func.SerFunction;
|
||||||
import org.dromara.hutool.core.func.SerSupplier;
|
import org.dromara.hutool.core.func.SerSupplier;
|
||||||
|
import org.dromara.hutool.core.io.IORuntimeException;
|
||||||
|
import org.dromara.hutool.core.io.IoUtil;
|
||||||
|
import org.dromara.hutool.core.io.file.FileUtil;
|
||||||
|
import org.dromara.hutool.core.io.resource.Resource;
|
||||||
|
import org.dromara.hutool.core.io.resource.ResourceUtil;
|
||||||
|
import org.dromara.hutool.core.io.watch.SimpleWatcher;
|
||||||
|
import org.dromara.hutool.core.io.watch.WatchMonitor;
|
||||||
|
import org.dromara.hutool.core.io.watch.WatchUtil;
|
||||||
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
import org.dromara.hutool.core.lang.getter.TypeGetter;
|
import org.dromara.hutool.core.lang.getter.TypeGetter;
|
||||||
import org.dromara.hutool.core.map.MapUtil;
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||||
@ -102,6 +101,16 @@ public final class Props extends Properties implements TypeGetter<CharSequence>
|
|||||||
return new Props(resource, charset);
|
return new Props(resource, charset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Properties}转为Props
|
||||||
|
*
|
||||||
|
* @param properties {@link Properties}
|
||||||
|
* @return Props
|
||||||
|
*/
|
||||||
|
public static Props of(final Properties properties) {
|
||||||
|
return new Props(properties);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- 构造方法 start
|
// ----------------------------------------------------------------------- 构造方法 start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -272,6 +281,37 @@ public final class Props extends Properties implements TypeGetter<CharSequence>
|
|||||||
return (String) value;
|
return (String) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取一个新的子属性,子属性键值对拥有公共前缀,以.分隔。
|
||||||
|
* <pre>
|
||||||
|
* a.b
|
||||||
|
* a.c
|
||||||
|
* b.a
|
||||||
|
* </pre>
|
||||||
|
* 则调用getSubProps("a");得到
|
||||||
|
* <pre>
|
||||||
|
* a.b
|
||||||
|
* a.c
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param prefix 前缀,可以不以.结尾
|
||||||
|
* @return 子属性
|
||||||
|
*/
|
||||||
|
public Props getSubProps(final String prefix) {
|
||||||
|
final Props subProps = new Props();
|
||||||
|
final String finalPrefix = StrUtil.addSuffixIfNot(prefix, StrUtil.DOT);
|
||||||
|
final int prefixLength = finalPrefix.length();
|
||||||
|
|
||||||
|
forEach((key, value) -> {
|
||||||
|
final String keyStr = key.toString();
|
||||||
|
if (StrUtil.startWith(keyStr, finalPrefix)) {
|
||||||
|
subProps.set(StrUtil.subSuf(keyStr, prefixLength), value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return subProps;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换为标准的{@link Properties}对象
|
* 转换为标准的{@link Properties}对象
|
||||||
*
|
*
|
||||||
@ -325,7 +365,28 @@ public final class Props extends Properties implements TypeGetter<CharSequence>
|
|||||||
*/
|
*/
|
||||||
public <T> T toBean(final Class<T> beanClass, final String prefix) {
|
public <T> T toBean(final Class<T> beanClass, final String prefix) {
|
||||||
final T bean = ConstructorUtil.newInstanceIfPossible(beanClass);
|
final T bean = ConstructorUtil.newInstanceIfPossible(beanClass);
|
||||||
return fillBean(bean, prefix);
|
return toBean(bean, prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将配置文件转换为Bean,支持嵌套Bean<br>
|
||||||
|
* 支持的表达式:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* persion
|
||||||
|
* persion.name
|
||||||
|
* persons[3]
|
||||||
|
* person.friends[5].name
|
||||||
|
* ['person']['friends'][5]['name']
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <T> Bean类型
|
||||||
|
* @param bean Bean对象
|
||||||
|
* @return Bean对象
|
||||||
|
* @since 4.6.3
|
||||||
|
*/
|
||||||
|
public <T> T toBean(final T bean) {
|
||||||
|
return toBean(bean, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -346,7 +407,7 @@ public final class Props extends Properties implements TypeGetter<CharSequence>
|
|||||||
* @return Bean对象
|
* @return Bean对象
|
||||||
* @since 4.6.3
|
* @since 4.6.3
|
||||||
*/
|
*/
|
||||||
public <T> T fillBean(final T bean, String prefix) {
|
public <T> T toBean(final T bean, String prefix) {
|
||||||
prefix = StrUtil.emptyIfNull(StrUtil.addSuffixIfNot(prefix, StrUtil.DOT));
|
prefix = StrUtil.emptyIfNull(StrUtil.addSuffixIfNot(prefix, StrUtil.DOT));
|
||||||
|
|
||||||
String key;
|
String key;
|
||||||
|
@ -88,7 +88,7 @@ public class PropsTest {
|
|||||||
Assertions.assertEquals(DateUtil.parse("2020-01-01"), systemConfig.getCreateTime());
|
Assertions.assertEquals(DateUtil.parse("2020-01-01"), systemConfig.getCreateTime());
|
||||||
Assertions.assertEquals(true, systemConfig.getIsInit());
|
Assertions.assertEquals(true, systemConfig.getIsInit());
|
||||||
Assertions.assertEquals("1", systemConfig.getStairPlan());
|
Assertions.assertEquals("1", systemConfig.getStairPlan());
|
||||||
Assertions.assertEquals(new Integer(2), systemConfig.getStageNum());
|
Assertions.assertEquals(Integer.valueOf(2), systemConfig.getStageNum());
|
||||||
Assertions.assertEquals("3", systemConfig.getVersion());
|
Assertions.assertEquals("3", systemConfig.getVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,5 +124,16 @@ public class PropsTest {
|
|||||||
private Date nextStageTime;//当前阶段结束日期/下一阶段开始日期
|
private Date nextStageTime;//当前阶段结束日期/下一阶段开始日期
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getSubTest() {
|
||||||
|
final Props props = new Props();
|
||||||
|
props.set("a.b", "1");
|
||||||
|
props.set("a.c", "2");
|
||||||
|
props.set("b.a", "3");
|
||||||
|
|
||||||
|
final Props subProps = props.getSubProps("a");
|
||||||
|
Assertions.assertEquals(2, subProps.size());
|
||||||
|
Assertions.assertEquals("1", subProps.getStr("b"));
|
||||||
|
Assertions.assertEquals("2", subProps.getStr("c"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user