连接池配置

Raod 3 years ago
parent 3e5a7ca928
commit d8fab4fe7b

@ -48,6 +48,12 @@
<version>2.2.6.RELEASE</version> <version>2.2.6.RELEASE</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency> <dependency>
<groupId>com.anji-plus</groupId> <groupId>com.anji-plus</groupId>
<artifactId>spring-boot-gaea</artifactId> <artifactId>spring-boot-gaea</artifactId>

@ -0,0 +1,99 @@
package com.anjiplus.template.gaea.business.config;
import com.alibaba.druid.pool.DruidDataSource;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Created by raodeming on 2021/8/6.
*/
@Component
@ConfigurationProperties(prefix = "spring.druid")
@Data
public class DruidProperties {
/**
* initgetConnection
*/
private int initialSize;
/**
*
*/
private int minIdle;
/**
*
*/
private int maxActive;
/**
* maxWait
*/
private int maxWait;
/**
* .Destroy线minEvictableIdleTimeMillis
*/
private int timeBetweenEvictionRunsMillis;
/**
* .
*/
private int minEvictableIdleTimeMillis;
/**
* .truetimeBetweenEvictionRun
*/
private boolean testWhileIdle;
/**
* PSCache
*/
private boolean poolPreparedStatements;
/**
* PSCache
*/
private int maxPoolPreparedStatementPerConnectionSize;
/**
*
*/
private int connectionErrorRetryAttempts;
/**
*
*/
private boolean breakAfterAcquireFailure;
/**
*
*/
private int timeBetweenConnectErrorMillis;
public DruidDataSource dataSource(String url, String username, String password, String driverClassName) {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(url);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
//configuration
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
datasource.setConnectionErrorRetryAttempts(connectionErrorRetryAttempts);
datasource.setBreakAfterAcquireFailure(breakAfterAcquireFailure);
datasource.setTimeBetweenConnectErrorMillis(timeBetweenConnectErrorMillis);
return datasource;
}
}

@ -0,0 +1,39 @@
package com.anjiplus.template.gaea.business.modules.dataSource.service;
import com.anjiplus.template.gaea.business.modules.dataSource.controller.dto.DataSourceDto;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Created by raodeming on 2021/8/6.
*/
public interface JdbcService {
/**
*
*
* @param id
*/
void removeJdbcConnectionPool(Long id);
/**
*
*
* @param dataSource
* @return
* @throws SQLException
*/
Connection getPooledConnection(DataSourceDto dataSource) throws SQLException;
/**
*
*
* @param dataSource
* @return
* @throws ClassNotFoundException driverName
* @throws SQLException
*/
Connection getUnPooledConnection(DataSourceDto dataSource) throws SQLException;
}

@ -17,9 +17,9 @@ import com.anjiplus.template.gaea.business.modules.dataSource.controller.dto.Dat
import com.anjiplus.template.gaea.business.modules.dataSource.controller.param.ConnectionParam; import com.anjiplus.template.gaea.business.modules.dataSource.controller.param.ConnectionParam;
import com.anjiplus.template.gaea.business.modules.dataSource.dao.DataSourceMapper; import com.anjiplus.template.gaea.business.modules.dataSource.dao.DataSourceMapper;
import com.anjiplus.template.gaea.business.modules.dataSource.dao.entity.DataSource; import com.anjiplus.template.gaea.business.modules.dataSource.dao.entity.DataSource;
import com.anjiplus.template.gaea.business.util.JdbcConstants;
import com.anjiplus.template.gaea.business.modules.dataSource.service.DataSourceService; import com.anjiplus.template.gaea.business.modules.dataSource.service.DataSourceService;
import com.anjiplus.template.gaea.business.util.JdbcUtil; import com.anjiplus.template.gaea.business.modules.dataSource.service.JdbcService;
import com.anjiplus.template.gaea.business.util.JdbcConstants;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -59,6 +59,9 @@ public class DataSourceServiceImpl implements DataSourceService {
@Autowired @Autowired
private DataSetParamService dataSetParamService; private DataSetParamService dataSetParamService;
@Autowired
private JdbcService jdbcService;
@Override @Override
public GaeaBaseMapper<DataSource> getMapper() { public GaeaBaseMapper<DataSource> getMapper() {
return dataSourceMapper; return dataSourceMapper;
@ -222,7 +225,7 @@ public class DataSourceServiceImpl implements DataSourceService {
analysisRelationalDbConfig(dto); analysisRelationalDbConfig(dto);
Connection pooledConnection = null; Connection pooledConnection = null;
try { try {
pooledConnection = JdbcUtil.getPooledConnection(dto); pooledConnection = jdbcService.getPooledConnection(dto);
PreparedStatement statement = pooledConnection.prepareStatement(dto.getDynSentence()); PreparedStatement statement = pooledConnection.prepareStatement(dto.getDynSentence());
ResultSet rs = statement.executeQuery(); ResultSet rs = statement.executeQuery();
@ -307,13 +310,18 @@ public class DataSourceServiceImpl implements DataSourceService {
public void testRelationalDb(DataSourceDto dto) { public void testRelationalDb(DataSourceDto dto) {
analysisRelationalDbConfig(dto); analysisRelationalDbConfig(dto);
try { try {
Connection unPooledConnection = JdbcUtil.getUnPooledConnection(dto); Connection unPooledConnection = jdbcService.getUnPooledConnection(dto);
String catalog = unPooledConnection.getCatalog(); String catalog = unPooledConnection.getCatalog();
log.info("数据库测试连接成功:{}", catalog); log.info("数据库测试连接成功:{}", catalog);
unPooledConnection.close(); unPooledConnection.close();
} catch (SQLException e) { } catch (SQLException e) {
log.error("error",e); log.error("error",e);
throw BusinessExceptionBuilder.build(ResponseCode.DATA_SOURCE_CONNECTION_FAILED, e.getMessage()); if (e.getCause() instanceof ClassNotFoundException) {
throw BusinessExceptionBuilder.build(ResponseCode.CLASS_NOT_FOUND, e.getCause().getMessage());
} else {
throw BusinessExceptionBuilder.build(ResponseCode.DATA_SOURCE_CONNECTION_FAILED, e.getMessage());
}
} }
} }
@ -418,6 +426,6 @@ public class DataSourceServiceImpl implements DataSourceService {
*/ */
@Override @Override
public void processAfterOperation(DataSource entity, BaseOperationEnum operationEnum) throws BusinessException { public void processAfterOperation(DataSource entity, BaseOperationEnum operationEnum) throws BusinessException {
JdbcUtil.removeJdbcConnectionPool(entity.getId()); jdbcService.removeJdbcConnectionPool(entity.getId());
} }
} }

@ -0,0 +1,96 @@
package com.anjiplus.template.gaea.business.modules.dataSource.service.impl;
import com.alibaba.druid.pool.DruidDataSource;
import com.anjiplus.template.gaea.business.config.DruidProperties;
import com.anjiplus.template.gaea.business.modules.dataSource.controller.dto.DataSourceDto;
import com.anjiplus.template.gaea.business.modules.dataSource.service.JdbcService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by raodeming on 2021/8/6.
*/
@Service
@Slf4j
public class JdbcServiceImpl implements JdbcService {
@Autowired
private DruidProperties druidProperties;
/**
* map
*/
static Map<Long, DruidDataSource> map = new ConcurrentHashMap<>();
public DruidDataSource getJdbcConnectionPool(DataSourceDto dataSource) {
if (map.containsKey(dataSource.getId())) {
return map.get(dataSource.getId());
} else {
try {
if (!map.containsKey(dataSource.getId())) {
DruidDataSource pool = druidProperties.dataSource(dataSource.getJdbcUrl(),
dataSource.getUsername(), dataSource.getPassword(), dataSource.getDriverName());
map.put(dataSource.getId(), pool);
log.info("创建连接池成功:{}", dataSource.getJdbcUrl());
}
return map.get(dataSource.getId());
} finally {
}
}
}
/**
*
*
* @param id
*/
@Override
public void removeJdbcConnectionPool(Long id) {
try {
DruidDataSource pool = map.get(id);
if (pool != null) {
log.info("remove pool success, datasourceId:{}", id);
map.remove(id);
}
} catch (Exception e) {
log.error("error", e);
} finally {
}
}
/**
*
*
* @param dataSource
* @return
* @throws SQLException
*/
@Override
public Connection getPooledConnection(DataSourceDto dataSource) throws SQLException{
DruidDataSource pool = getJdbcConnectionPool(dataSource);
return pool.getConnection();
}
/**
*
*
* @param dataSource
* @return
* @throws ClassNotFoundException driverName
* @throws SQLException
*/
@Override
public Connection getUnPooledConnection(DataSourceDto dataSource) throws SQLException {
DruidDataSource druidDataSource = druidProperties.dataSource(dataSource.getJdbcUrl(),
dataSource.getUsername(), dataSource.getPassword(), dataSource.getDriverName());
return druidDataSource.getConnection();
}
}

@ -1,92 +0,0 @@
package com.anjiplus.template.gaea.business.util;
import com.anji.plus.gaea.exception.BusinessExceptionBuilder;
import com.anjiplus.template.gaea.business.code.ResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* Created by raodeming on 2021/4/19.
*/
@Slf4j
public final class DriverClassUtil {
/**
*
*/
private static final Map<String, String> DRIVER_CLASS_MAP;
static {
DRIVER_CLASS_MAP = new HashMap<>(32);
DRIVER_CLASS_MAP.put("jdbc:db2", "COM.ibm.db2.jdbc.app.DB2Driver");
DRIVER_CLASS_MAP.put("jdbc:firebirdsql", "org.firebirdsql.jdbc.FBDriver");
DRIVER_CLASS_MAP.put("jdbc:edbc", "ca.edbc.jdbc.EdbcDriver");
DRIVER_CLASS_MAP.put("jdbc:pointbase", "com.pointbase.jdbc.jdbcUniversalDriver");
DRIVER_CLASS_MAP.put("jdbc:fake", "com.alibaba.druid.mock.MockDriver");
DRIVER_CLASS_MAP.put("jdbc:informix-sqli", "com.informix.jdbc.IfxDriver");
DRIVER_CLASS_MAP.put("jdbc:sqlite", "org.sqlite.JDBC");
DRIVER_CLASS_MAP.put("jdbc:microsoft", "com.microsoft.jdbc.sqlserver.SQLServerDriver");
DRIVER_CLASS_MAP.put("jdbc:hsqldb", "org.hsqldb.jdbcDriver");
DRIVER_CLASS_MAP.put("jdbc:postgresql", "org.postgresql.Driver");
DRIVER_CLASS_MAP.put("jdbc:ingres", "com.ingres.jdbc.IngresDriver");
DRIVER_CLASS_MAP.put("jdbc:cloudscape", "COM.cloudscape.core.JDBCDriver");
DRIVER_CLASS_MAP.put("jdbc:JSQLConnect", "com.jnetdirect.jsql.JSQLDriver");
DRIVER_CLASS_MAP.put("jdbc:derby", "org.apache.derby.jdbc.EmbeddedDriver");
DRIVER_CLASS_MAP.put("jdbc:timesten", "com.timesten.jdbc.TimesTenDriver");
DRIVER_CLASS_MAP.put("jdbc:interbase", "interbase.interclient.Driver");
DRIVER_CLASS_MAP.put("jdbc:h2", "org.h2.Driver");
DRIVER_CLASS_MAP.put("jdbc:as400", "com.ibm.as400.access.AS400JDBCDriver");
DRIVER_CLASS_MAP.put("jdbc:sybase:Tds", "com.sybase.jdbc2.jdbc.SybDriver");
DRIVER_CLASS_MAP.put("jdbc:mock", "com.alibaba.druid.mock.MockDriver");
DRIVER_CLASS_MAP.put("jdbc:oracle", "oracle.jdbc.driver.OracleDriver");
DRIVER_CLASS_MAP.put("jdbc:mysql", "com.mysql.jdbc.Driver");
DRIVER_CLASS_MAP.put("jdbc:odps", "com.aliyun.odps.jdbc.OdpsDriver");
DRIVER_CLASS_MAP.put("jdbc:mckoi", "com.mckoi.JDBCDriver");
DRIVER_CLASS_MAP.put("jdbc:jtds", "net.sourceforge.jtds.jdbc.Driver");
DRIVER_CLASS_MAP.put("jdbc:sapdb", "com.sap.dbtech.jdbc.DriverSapDB");
DRIVER_CLASS_MAP.put("jdbc:JTurbo", "com.newatlanta.jturbo.driver.Driver");
DRIVER_CLASS_MAP.put("jdbc:mimer:multi1", "com.mimer.jdbc.Driver");
}
/**
*
* @param driverClass
* @param url
*/
public static void loadDriverClass(String driverClass, final String url) {
if(StringUtils.isEmpty(driverClass)) {
driverClass = getDriverClassByUrl(url);
}
try {
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
log.error("error", e);
throw BusinessExceptionBuilder.build(ResponseCode.CLASS_NOT_FOUND);
}
}
/**
* URL
*
* 1. url
* 2.
* @param url url
* @return
*/
private static String getDriverClassByUrl(final String url) {
for(Map.Entry<String, String> entry : DRIVER_CLASS_MAP.entrySet()) {
String urlPrefix = entry.getKey();
if(url.startsWith(urlPrefix)) {
return entry.getValue();
}
}
throw BusinessExceptionBuilder.build(ResponseCode.CLASS_NOT_FOUND, "Can't auto find match driver class for url: " + url);
}
}

@ -1,103 +0,0 @@
package com.anjiplus.template.gaea.business.util;
import com.alibaba.druid.pool.DruidDataSource;
import com.anjiplus.template.gaea.business.modules.dataSource.controller.dto.DataSourceDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by raodeming on 2021/3/18.
*/
@Slf4j
public class JdbcUtil {
/**
* map
*/
static Map<Long, DruidDataSource> map = new ConcurrentHashMap<>();
public static DruidDataSource getJdbcConnectionPool(DataSourceDto dataSource) {
if (map.containsKey(dataSource.getId())) {
return map.get(dataSource.getId());
} else {
try {
if (!map.containsKey(dataSource.getId())) {
DruidDataSource pool = new DruidDataSource();
pool.setUrl(dataSource.getJdbcUrl());
pool.setUsername(dataSource.getUsername());
pool.setPassword(dataSource.getPassword());
pool.setDriverClassName(dataSource.getDriverName());
//下面都是可选的配置
pool.setInitialSize(10); //初始连接数默认0
pool.setMaxActive(30); //最大连接数默认8
pool.setMinIdle(10); //最小闲置数
pool.setMaxWait(2000); //获取连接的最大等待时间,单位毫秒
pool.setPoolPreparedStatements(true); //缓存PreparedStatement默认false
pool.setMaxOpenPreparedStatements(20); //缓存PreparedStatement的最大数量默认-1不缓存。大于0时会自动开启缓存PreparedStatement所以可以省略上一句代码
pool.setConnectionErrorRetryAttempts(0);
pool.setBreakAfterAcquireFailure(true);
map.put(dataSource.getId(), pool);
log.info("创建连接池成功:{}", dataSource.getJdbcUrl());
}
return map.get(dataSource.getId());
} finally {
}
}
}
/**
*
*
* @param id
*/
public static void removeJdbcConnectionPool(Long id) {
try {
DruidDataSource pool = map.get(id);
if (pool != null) {
log.info("remove pool success, datasourceId:{}", id);
map.remove(id);
}
} catch (Exception e) {
log.error("error", e);
} finally {
}
}
/**
*
*
* @param dataSource
* @return
* @throws SQLException
*/
public static Connection getPooledConnection(DataSourceDto dataSource) throws SQLException {
DruidDataSource pool = getJdbcConnectionPool(dataSource);
return pool.getConnection();
}
/**
*
*
* @param dataSource
* @return
* @throws ClassNotFoundException driverName
* @throws SQLException
*/
public static Connection getUnPooledConnection(DataSourceDto dataSource) throws SQLException {
DriverClassUtil.loadDriverClass(dataSource.getDriverName(), dataSource.getJdbcUrl());
if (StringUtils.isBlank(dataSource.getUsername()) && StringUtils.isBlank(dataSource.getPassword())) {
return DriverManager.getConnection(dataSource.getJdbcUrl());
}
return DriverManager.getConnection(dataSource.getJdbcUrl(),
dataSource.getUsername(), dataSource.getPassword());
}
}

@ -22,6 +22,20 @@ spring:
url: jdbc:mysql://10.108.26.197:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false url: jdbc:mysql://10.108.26.197:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
username: root username: root
password: appuser@anji password: appuser@anji
#数据源连接池配置
druid:
initial-size: 10 # 初始化时建立物理连接的个数。初始化发生在显示调用init方法或者第一次getConnection时
min-idle: 10 # 最小连接池数量
maxActive: 200 # 最大连接池数量
maxWait: 60000 # 获取连接时最大等待时间单位毫秒。配置了maxWait之后缺省启用公平锁并发效率会有所下降如果需要可以通过配置
timeBetweenEvictionRunsMillis: 60000 # 关闭空闲连接的检测时间间隔.Destroy线程会检测连接的间隔时间如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。
minEvictableIdleTimeMillis: 300000 # 连接的最小生存时间.连接保持空闲而不被驱逐的最小时间
testWhileIdle: true # 申请连接时检测空闲时间,根据空闲时间再检测连接是否有效.建议配置为true不影响性能并且保证安全性。申请连接的时候检测如果空闲时间大于timeBetweenEvictionRun
poolPreparedStatements: true # 开启PSCache
maxPoolPreparedStatementPerConnectionSize: 20 #设置PSCache值
connectionErrorRetryAttempts: 3 # 连接出错后再尝试连接三次
breakAfterAcquireFailure: true # 数据库服务宕机自动重连机制
timeBetweenConnectErrorMillis: 300000 # 连接出错后重试时间间隔
flyway: flyway:
baseline-on-migrate: true baseline-on-migrate: true
#数据库连接配置 #数据库连接配置

Loading…
Cancel
Save