diff --git a/report-core/pom.xml b/report-core/pom.xml
index fc1d8bd7..ec175901 100644
--- a/report-core/pom.xml
+++ b/report-core/pom.xml
@@ -48,6 +48,12 @@
2.2.6.RELEASE
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
com.anji-plus
spring-boot-gaea
diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/config/DruidProperties.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/config/DruidProperties.java
new file mode 100644
index 00000000..bed72ad5
--- /dev/null
+++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/config/DruidProperties.java
@@ -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 {
+ /**
+ * 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
+ */
+ private int initialSize;
+
+ /**
+ * 最小连接池数量
+ */
+ private int minIdle;
+
+ /**
+ * 最大连接池数量
+ */
+ private int maxActive;
+
+ /**
+ * 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置
+ */
+ private int maxWait;
+
+ /**
+ * 关闭空闲连接的检测时间间隔.Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。
+ */
+ private int timeBetweenEvictionRunsMillis;
+
+ /**
+ * 连接的最小生存时间.连接保持空闲而不被驱逐的最小时间
+ */
+ private int minEvictableIdleTimeMillis;
+
+ /**
+ * 申请连接时检测空闲时间,根据空闲时间再检测连接是否有效.建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRun
+ */
+ 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;
+ }
+}
diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataSource/service/JdbcService.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataSource/service/JdbcService.java
new file mode 100644
index 00000000..dc1041b3
--- /dev/null
+++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataSource/service/JdbcService.java
@@ -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;
+}
diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataSource/service/impl/DataSourceServiceImpl.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataSource/service/impl/DataSourceServiceImpl.java
index 48c7d80f..08f5b1b8 100644
--- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataSource/service/impl/DataSourceServiceImpl.java
+++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataSource/service/impl/DataSourceServiceImpl.java
@@ -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.dao.DataSourceMapper;
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.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.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
@@ -59,6 +59,9 @@ public class DataSourceServiceImpl implements DataSourceService {
@Autowired
private DataSetParamService dataSetParamService;
+ @Autowired
+ private JdbcService jdbcService;
+
@Override
public GaeaBaseMapper getMapper() {
return dataSourceMapper;
@@ -222,7 +225,7 @@ public class DataSourceServiceImpl implements DataSourceService {
analysisRelationalDbConfig(dto);
Connection pooledConnection = null;
try {
- pooledConnection = JdbcUtil.getPooledConnection(dto);
+ pooledConnection = jdbcService.getPooledConnection(dto);
PreparedStatement statement = pooledConnection.prepareStatement(dto.getDynSentence());
ResultSet rs = statement.executeQuery();
@@ -307,13 +310,18 @@ public class DataSourceServiceImpl implements DataSourceService {
public void testRelationalDb(DataSourceDto dto) {
analysisRelationalDbConfig(dto);
try {
- Connection unPooledConnection = JdbcUtil.getUnPooledConnection(dto);
+ Connection unPooledConnection = jdbcService.getUnPooledConnection(dto);
String catalog = unPooledConnection.getCatalog();
log.info("数据库测试连接成功:{}", catalog);
unPooledConnection.close();
} catch (SQLException 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
public void processAfterOperation(DataSource entity, BaseOperationEnum operationEnum) throws BusinessException {
- JdbcUtil.removeJdbcConnectionPool(entity.getId());
+ jdbcService.removeJdbcConnectionPool(entity.getId());
}
}
diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataSource/service/impl/JdbcServiceImpl.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataSource/service/impl/JdbcServiceImpl.java
new file mode 100644
index 00000000..a7a49430
--- /dev/null
+++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataSource/service/impl/JdbcServiceImpl.java
@@ -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 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();
+ }
+
+}
diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/util/DriverClassUtil.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/util/DriverClassUtil.java
deleted file mode 100644
index 02b6dc82..00000000
--- a/report-core/src/main/java/com/anjiplus/template/gaea/business/util/DriverClassUtil.java
+++ /dev/null
@@ -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 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 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);
- }
-
-}
diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/util/JdbcUtil.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/util/JdbcUtil.java
deleted file mode 100644
index 2b36ff56..00000000
--- a/report-core/src/main/java/com/anjiplus/template/gaea/business/util/JdbcUtil.java
+++ /dev/null
@@ -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 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());
- }
-
-
-}
diff --git a/report-core/src/main/resources/bootstrap.yml b/report-core/src/main/resources/bootstrap.yml
index fa5efe7b..8bdadede 100644
--- a/report-core/src/main/resources/bootstrap.yml
+++ b/report-core/src/main/resources/bootstrap.yml
@@ -22,6 +22,20 @@ spring:
url: jdbc:mysql://10.108.26.197:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
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:
baseline-on-migrate: true
#数据库连接配置