数据库问文档重构

This commit is contained in:
暮光:城中城
2019-07-04 21:52:39 +08:00
parent e3ed105f49
commit 6c1f4e123a
49 changed files with 13653 additions and 198 deletions

View File

@@ -0,0 +1,95 @@
package com.zyplayer.doc.db.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.data.config.security.DocUserDetails;
import com.zyplayer.doc.data.config.security.DocUserUtil;
import com.zyplayer.doc.data.repository.manage.entity.DbDatasource;
import com.zyplayer.doc.data.service.manage.DbDatasourceService;
import com.zyplayer.doc.db.framework.configuration.DatasourceUtil;
import com.zyplayer.doc.db.framework.db.bean.DatabaseFactoryBean;
import com.zyplayer.doc.db.framework.db.bean.DatabaseRegistrationBean;
import com.zyplayer.doc.db.framework.json.DocDbResponseJson;
import com.zyplayer.doc.db.framework.json.ResponseJson;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.*;
/**
* 数据源控制器
*
* @author 暮光:城中城
* @since 2019年6月29日
*/
@AuthMan
@RestController
@RequestMapping("/zyplayer-doc-db/datasource")
public class DbDatasourceController {
@Resource
DatabaseRegistrationBean databaseRegistrationBean;
@Resource
DbDatasourceService dbDatasourceService;
@PostMapping(value = "/list")
public ResponseJson list() {
QueryWrapper<DbDatasource> wrapper = new QueryWrapper<>();
wrapper.eq("yn", 1);
List<DbDatasource> datasourceList = dbDatasourceService.list(wrapper);
return DocDbResponseJson.ok(datasourceList);
}
@PostMapping(value = "/update")
public ResponseJson update(DbDatasource dbDatasource) {
if (StringUtils.isBlank(dbDatasource.getDriverClassName())) {
return DocDbResponseJson.warn("驱动类必选");
} else if (StringUtils.isBlank(dbDatasource.getSourceUrl())) {
return DocDbResponseJson.warn("地址必填");
} else if (StringUtils.isBlank(dbDatasource.getSourceName())) {
return DocDbResponseJson.warn("用户名必填");
} else if (StringUtils.isBlank(dbDatasource.getSourcePassword())) {
return DocDbResponseJson.warn("密码必填");
}
Long sourceId = Optional.ofNullable(dbDatasource.getId()).orElse(0L);
if (sourceId > 0) {
dbDatasourceService.updateById(dbDatasource);
} else {
DocUserDetails currentUser = DocUserUtil.getCurrentUser();
dbDatasource.setCreateTime(new Date());
dbDatasource.setCreateUserId(currentUser.getUserId());
dbDatasource.setYn(1);
dbDatasourceService.save(dbDatasource);
}
List<DatabaseFactoryBean> newFactoryBeanList = new LinkedList<>();
List<DatabaseFactoryBean> databaseFactoryBeanList = databaseRegistrationBean.getDatabaseFactoryBeanList();
for (DatabaseFactoryBean factoryBean : databaseFactoryBeanList) {
if (Objects.equals(factoryBean.getId(), sourceId)) {
try {
// 关闭旧的数据源
factoryBean.getDataSource().close();
factoryBean.getDataSource().destroy();
} catch (Exception e) {
e.printStackTrace();
}
} else {
newFactoryBeanList.add(factoryBean);
}
}
// 创建新的数据源
DatabaseFactoryBean databaseFactoryBean = DatasourceUtil.createDatabaseFactoryBean(dbDatasource);
if (databaseFactoryBean != null) {
newFactoryBeanList.add(databaseFactoryBean);
}
databaseRegistrationBean.setDatabaseFactoryBeanList(newFactoryBeanList);
if (databaseFactoryBean == null) {
return DocDbResponseJson.warn("创建数据源失败,请检查配置是否正确");
}
return DocDbResponseJson.ok();
}
}

View File

@@ -1,36 +1,24 @@
package com.zyplayer.doc.db.framework.configuration;
import java.sql.DatabaseMetaData;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import javax.sql.DataSource;
import com.zyplayer.doc.db.framework.db.bean.DbConfigBean;
import com.zyplayer.doc.db.framework.db.interceptor.SqlLogInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zyplayer.doc.data.repository.manage.entity.DbDatasource;
import com.zyplayer.doc.data.service.manage.DbDatasourceService;
import com.zyplayer.doc.db.framework.db.bean.DatabaseFactoryBean;
import com.zyplayer.doc.db.framework.db.bean.DatabaseRegistrationBean;
import org.springframework.context.ApplicationListener;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Component;
import com.zyplayer.doc.db.framework.db.bean.DatabaseFactoryBean;
import com.zyplayer.doc.db.framework.db.bean.DatabaseFactoryBean.DatabaseProduct;
import com.zyplayer.doc.db.framework.db.bean.DatabaseRegistrationBean;
import java.util.LinkedList;
import java.util.List;
@Component
public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
@javax.annotation.Resource
DatabaseRegistrationBean databaseRegistrationBean;
@javax.annotation.Resource
DbDatasourceService dbDatasourceService;
private volatile static boolean IS_INIT = false;
@@ -41,76 +29,15 @@ public class ApplicationListenerBean implements ApplicationListener<ContextRefre
}
// 会被调用两次
IS_INIT = true;
Integer dataSourceIndex = 0;
SqlLogInterceptor sqlLogInterceptor = new SqlLogInterceptor();
List<DatabaseFactoryBean> databaseFactoryBeanList = new LinkedList<>();
for (DbConfigBean dbConfigBean : databaseRegistrationBean.getDbConfigList()) {
try {
// 数据源配置
Properties xaProperties = new Properties();
xaProperties.setProperty("driverClassName", dbConfigBean.getDriverClassName());
xaProperties.setProperty("url", dbConfigBean.getUrl());
xaProperties.setProperty("username", dbConfigBean.getUsername());
xaProperties.setProperty("password", dbConfigBean.getPassword());
xaProperties.setProperty("maxActive", "500");
xaProperties.setProperty("testOnBorrow", "true");
xaProperties.setProperty("testWhileIdle", "true");
xaProperties.setProperty("validationQuery", "select 'x'");
// 数据源
AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
dataSource.setXaProperties(xaProperties);
dataSource.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
dataSource.setUniqueResourceName("zyplayer-doc-db" + (dataSourceIndex++));
dataSource.setMaxPoolSize(500);
dataSource.setMinPoolSize(1);
dataSource.setMaxLifetime(60);
// 描述连接信息的对象
DatabaseFactoryBean databaseFactoryBean = new DatabaseFactoryBean();
DatabaseMetaData metaData = dataSource.getConnection().getMetaData();
String productName = metaData.getDatabaseProductName().toLowerCase();
Resource[] resources = null;
String dbUrl = metaData.getURL();
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
if (productName.indexOf("mysql") >= 0) {
// jdbc:mysql://192.168.0.1:3306/user_info?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&autoReconnect=true
String[] urlParamArr = dbUrl.split("\\?");
String[] urlDbNameArr = urlParamArr[0].split("/");
if (urlDbNameArr.length >= 2) {
databaseFactoryBean.setDbName(urlDbNameArr[urlDbNameArr.length - 1]);
databaseFactoryBean.setHost(urlDbNameArr[urlDbNameArr.length - 2]);
}
databaseFactoryBean.setDatabaseProduct(DatabaseProduct.MYSQL);
resources = resolver.getResources("classpath:com/zyplayer/doc/db/framework/db/mapper/mysql/*.xml");
} else if (productName.indexOf("sql server") >= 0) {
// jdbc:jtds:sqlserver://192.168.0.1:33434;socketTimeout=60;DatabaseName=user_info;
String[] urlParamArr = dbUrl.split(";");
String[] urlDbNameArr = urlParamArr[0].split("/");
databaseFactoryBean.setHost(urlDbNameArr[urlDbNameArr.length - 1]);
for (String urlParam : urlParamArr) {
String[] keyValArr = urlParam.split("=");
if (keyValArr.length >= 2 && keyValArr[0].equalsIgnoreCase("DatabaseName")) {
databaseFactoryBean.setDbName(keyValArr[1]);
}
}
databaseFactoryBean.setDatabaseProduct(DatabaseProduct.SQLSERVER);
resources = resolver.getResources("classpath:com/zyplayer/doc/db/framework/db/mapper/sqlserver/*.xml");
}
if (resources == null) {
continue;
}
// 创建sqlSessionTemplate
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(resources);
sqlSessionFactoryBean.setPlugins(new Interceptor[]{sqlLogInterceptor});
SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactoryBean.getObject());
// 组装自定义的bean
databaseFactoryBean.setDataSource(dataSource);
databaseFactoryBean.setSqlSessionTemplate(sqlSessionTemplate);
databaseFactoryBean.setUrl(dbUrl);
QueryWrapper<DbDatasource> wrapper = new QueryWrapper<>();
wrapper.eq("yn", 1);
List<DbDatasource> datasourceList = dbDatasourceService.list(wrapper);
for (DbDatasource dbDatasource : datasourceList) {
DatabaseFactoryBean databaseFactoryBean = DatasourceUtil.createDatabaseFactoryBean(dbDatasource);
if (databaseFactoryBean != null) {
databaseFactoryBeanList.add(databaseFactoryBean);
} catch (Exception e) {
e.printStackTrace();
}
}
databaseRegistrationBean.setDatabaseFactoryBeanList(databaseFactoryBeanList);

View File

@@ -0,0 +1,91 @@
package com.zyplayer.doc.db.framework.configuration;
import com.zyplayer.doc.data.repository.manage.entity.DbDatasource;
import com.zyplayer.doc.db.framework.db.bean.DatabaseFactoryBean;
import com.zyplayer.doc.db.framework.db.interceptor.SqlLogInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import java.sql.DatabaseMetaData;
import java.util.Properties;
public class DatasourceUtil {
private static SqlLogInterceptor sqlLogInterceptor = new SqlLogInterceptor();
public static DatabaseFactoryBean createDatabaseFactoryBean(DbDatasource dbDatasource){
try {
// 数据源配置
Properties xaProperties = new Properties();
xaProperties.setProperty("driverClassName", dbDatasource.getDriverClassName());
xaProperties.setProperty("url", dbDatasource.getSourceUrl());
xaProperties.setProperty("username", dbDatasource.getSourceName());
xaProperties.setProperty("password", dbDatasource.getSourcePassword());
xaProperties.setProperty("maxActive", "500");
xaProperties.setProperty("breakAfterAcquireFailure", "true");
xaProperties.setProperty("testOnBorrow", "true");
xaProperties.setProperty("testWhileIdle", "true");
xaProperties.setProperty("validationQuery", "select 'x'");
// 数据源
AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
dataSource.setXaProperties(xaProperties);
dataSource.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
dataSource.setUniqueResourceName("zyplayer-doc-db" + dbDatasource.getId());
dataSource.setMaxPoolSize(500);
dataSource.setMinPoolSize(1);
dataSource.setMaxLifetime(60);
// 描述连接信息的对象
DatabaseFactoryBean databaseFactoryBean = new DatabaseFactoryBean();
DatabaseMetaData metaData = dataSource.getConnection().getMetaData();
String productName = metaData.getDatabaseProductName().toLowerCase();
Resource[] resources = null;
String dbUrl = metaData.getURL();
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
if (productName.indexOf("mysql") >= 0) {
// jdbc:mysql://192.168.0.1:3306/user_info?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&autoReconnect=true
String[] urlParamArr = dbUrl.split("\\?");
String[] urlDbNameArr = urlParamArr[0].split("/");
if (urlDbNameArr.length >= 2) {
databaseFactoryBean.setDbName(urlDbNameArr[urlDbNameArr.length - 1]);
databaseFactoryBean.setHost(urlDbNameArr[urlDbNameArr.length - 2]);
}
databaseFactoryBean.setDatabaseProduct(DatabaseFactoryBean.DatabaseProduct.MYSQL);
resources = resolver.getResources("classpath:com/zyplayer/doc/db/framework/db/mapper/mysql/*.xml");
} else if (productName.indexOf("sql server") >= 0) {
// jdbc:jtds:sqlserver://192.168.0.1:33434;socketTimeout=60;DatabaseName=user_info;
String[] urlParamArr = dbUrl.split(";");
String[] urlDbNameArr = urlParamArr[0].split("/");
databaseFactoryBean.setHost(urlDbNameArr[urlDbNameArr.length - 1]);
for (String urlParam : urlParamArr) {
String[] keyValArr = urlParam.split("=");
if (keyValArr.length >= 2 && keyValArr[0].equalsIgnoreCase("DatabaseName")) {
databaseFactoryBean.setDbName(keyValArr[1]);
}
}
databaseFactoryBean.setDatabaseProduct(DatabaseFactoryBean.DatabaseProduct.SQLSERVER);
resources = resolver.getResources("classpath:com/zyplayer/doc/db/framework/db/mapper/sqlserver/*.xml");
}
if (resources == null) {
return null;
}
// 创建sqlSessionTemplate
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(resources);
sqlSessionFactoryBean.setPlugins(new Interceptor[]{sqlLogInterceptor});
SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactoryBean.getObject());
// 组装自定义的bean
databaseFactoryBean.setId(dbDatasource.getId());
databaseFactoryBean.setDataSource(dataSource);
databaseFactoryBean.setSqlSessionTemplate(sqlSessionTemplate);
databaseFactoryBean.setUrl(dbUrl);
return databaseFactoryBean;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@@ -1,72 +1,80 @@
package com.zyplayer.doc.db.framework.db.bean;
import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionTemplate;
/**
* 描述连接信息的对象
* @author 暮光:城中城
* @since 2018年8月8日
*/
public class DatabaseFactoryBean {
private DataSource dataSource;
private SqlSessionTemplate sqlSessionTemplate;
private String url;
private String host;
private String dbName;
private DatabaseProduct databaseProduct;
public static enum DatabaseProduct {
MYSQL, SQLSERVER
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
public DatabaseProduct getDatabaseProduct() {
return databaseProduct;
}
public void setDatabaseProduct(DatabaseProduct databaseProduct) {
this.databaseProduct = databaseProduct;
}
public SqlSessionTemplate getSqlSessionTemplate() {
return sqlSessionTemplate;
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
}
package com.zyplayer.doc.db.framework.db.bean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
/**
* 描述连接信息的对象
* @author 暮光:城中城
* @since 2018年8月8日
*/
public class DatabaseFactoryBean {
private Long id;
private AtomikosDataSourceBean dataSource;
private SqlSessionTemplate sqlSessionTemplate;
private String url;
private String host;
private String dbName;
private DatabaseProduct databaseProduct;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public static enum DatabaseProduct {
MYSQL, SQLSERVER
}
public AtomikosDataSourceBean getDataSource() {
return dataSource;
}
public void setDataSource(AtomikosDataSourceBean dataSource) {
this.dataSource = dataSource;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
public DatabaseProduct getDatabaseProduct() {
return databaseProduct;
}
public void setDatabaseProduct(DatabaseProduct databaseProduct) {
this.databaseProduct = databaseProduct;
}
public SqlSessionTemplate getSqlSessionTemplate() {
return sqlSessionTemplate;
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
}