Compare commits

...

1 Commits

9 changed files with 304 additions and 34 deletions

View File

@ -2,6 +2,7 @@ package com.zcloud.config;
import javax.sql.DataSource; import javax.sql.DataSource;
import com.zcloud.plugins.DynamicDataSource;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan; import org.mybatis.spring.annotation.MapperScan;
@ -16,6 +17,9 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidDataSource;
import java.util.HashMap;
import java.util.Map;
/** /**
* *
* luoxiaobao * luoxiaobao
@ -29,21 +33,31 @@ public class MasterDataSourceConfig {
static final String MAPPER_LOCATION = "classpath:mybatis/datasource/*/*.xml"; //扫描的 xml 目录 static final String MAPPER_LOCATION = "classpath:mybatis/datasource/*/*.xml"; //扫描的 xml 目录
static final String CONFIG_LOCATION = "classpath:mybatis/datasource/mybatis-config.xml"; //自定义的mybatis config 文件位置 static final String CONFIG_LOCATION = "classpath:mybatis/datasource/mybatis-config.xml"; //自定义的mybatis config 文件位置
static final String TYPE_ALIASES_PACKAGE = "com.zcloud.entity"; //扫描的 实体类 目录 static final String TYPE_ALIASES_PACKAGE = "com.zcloud.entity"; //扫描的 实体类 目录
@Value("${datasource.no1.url}") @Value("${datasource.no1.url}")
private String url; private String url;
@Value("${datasource.no1.username}") @Value("${datasource.no1.username}")
private String user; private String user;
@Value("${datasource.no1.password}") @Value("${datasource.no1.password}")
private String password; private String password;
@Value("${datasource.no1.driver-class-name}") @Value("${datasource.no1.driver-class-name}")
private String driverClass; private String driverClass;
@Value("${datasource.slave.no1.driver-class-name}")
private String no1DataSourceSlaveDriver;
@Value("${datasource.slave.no1.url}")
private String no1DataSourceSlaveUrl;
@Value("${datasource.slave.no1.username}")
private String no1DataSourceSlaveUser;
@Value("${datasource.slave.no1.password}")
private String no1DataSourceSlavePassword;
@Bean(name = "masterDataSource") @Bean(name = "masterDataSource")
@Primary
public DataSource masterDataSource() { public DataSource masterDataSource() {
DruidDataSource dataSource = new DruidDataSource(); DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClass); dataSource.setDriverClassName(driverClass);
@ -52,18 +66,37 @@ public class MasterDataSourceConfig {
dataSource.setPassword(password); dataSource.setPassword(password);
return dataSource; return dataSource;
} }
@Bean(name = "masterDataSourceSlave")
public DataSource masterDataSourceSlave() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(no1DataSourceSlaveDriver);
dataSource.setUrl(no1DataSourceSlaveUrl);
dataSource.setUsername(no1DataSourceSlaveUser);
dataSource.setPassword(no1DataSourceSlavePassword);
return dataSource;
}
@Bean(name = "masterTransactionManager") @Bean(name = "masterTransactionManager")
@Primary @Primary
public DataSourceTransactionManager masterTransactionManager() { public DataSourceTransactionManager masterTransactionManager() {
return new DataSourceTransactionManager(masterDataSource()); return new DataSourceTransactionManager(masterDataSource());
} }
@Bean(name = "dynamicDataSourceNo1")
public DataSource dynamicDataSource(
@Qualifier("masterDataSource") DataSource masterDataSource,
@Qualifier("masterDataSourceSlave") DataSource masterDataSourceSlave) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> dataSourceMap = new HashMap<>();
dataSourceMap.put("no1DataSource", masterDataSource);
dataSourceMap.put("no1DataSourceSlave", masterDataSourceSlave);
dynamicDataSource.setTargetDataSources(dataSourceMap);
dynamicDataSource.setDefaultTargetDataSource(masterDataSource);
return dynamicDataSource;
}
@Bean(name = "masterSqlSessionFactory") @Bean(name = "masterSqlSessionFactory")
@Primary @Primary
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource)throws Exception { public SqlSessionFactory masterSqlSessionFactory(@Qualifier("dynamicDataSourceNo1") DataSource dynamicDataSource)throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(masterDataSource); sessionFactory.setDataSource(dynamicDataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MasterDataSourceConfig.MAPPER_LOCATION)); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MasterDataSourceConfig.MAPPER_LOCATION));
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(MasterDataSourceConfig.CONFIG_LOCATION)); sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(MasterDataSourceConfig.CONFIG_LOCATION));
sessionFactory.setTypeAliasesPackage(MasterDataSourceConfig.TYPE_ALIASES_PACKAGE); sessionFactory.setTypeAliasesPackage(MasterDataSourceConfig.TYPE_ALIASES_PACKAGE);

View File

@ -2,6 +2,7 @@ package com.zcloud.config;
import javax.sql.DataSource; import javax.sql.DataSource;
import com.zcloud.plugins.DynamicDataSource;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan; import org.mybatis.spring.annotation.MapperScan;
@ -15,6 +16,9 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidDataSource;
import java.util.HashMap;
import java.util.Map;
/** /**
* *
* luoxiaobao * luoxiaobao
@ -28,19 +32,27 @@ public class No2DataSourceConfig {
static final String MAPPER_LOCATION = "classpath:mybatis/dsno2/*/*.xml"; //扫描的 xml 目录 static final String MAPPER_LOCATION = "classpath:mybatis/dsno2/*/*.xml"; //扫描的 xml 目录
static final String CONFIG_LOCATION = "classpath:mybatis/dsno2/mybatis-config.xml"; //自定义的mybatis config 文件位置 static final String CONFIG_LOCATION = "classpath:mybatis/dsno2/mybatis-config.xml"; //自定义的mybatis config 文件位置
static final String TYPE_ALIASES_PACKAGE = "ocom.zcloud.entity"; //扫描的 实体类 目录 static final String TYPE_ALIASES_PACKAGE = "ocom.zcloud.entity"; //扫描的 实体类 目录
@Value("${datasource.no2.url}") @Value("${datasource.no2.url}")
private String url; private String url;
@Value("${datasource.no2.username}") @Value("${datasource.no2.username}")
private String user; private String user;
@Value("${datasource.no2.password}") @Value("${datasource.no2.password}")
private String password; private String password;
@Value("${datasource.no2.driver-class-name}") @Value("${datasource.no2.driver-class-name}")
private String driverClass; private String driverClass;
@Value("${datasource.slave.no2.driver-class-name}")
private String no2DataSourceSlaveDriver;
@Value("${datasource.slave.no2.url}")
private String no2DataSourceSlaveUrl;
@Value("${datasource.slave.no2.username}")
private String no2DataSourceSlaveUser;
@Value("${datasource.slave.no2.password}")
private String no2DataSourceSlavePassword;
@Bean(name = "no2DataSource") @Bean(name = "no2DataSource")
public DataSource no2DataSource() { public DataSource no2DataSource() {
DruidDataSource dataSource = new DruidDataSource(); DruidDataSource dataSource = new DruidDataSource();
@ -50,19 +62,41 @@ public class No2DataSourceConfig {
dataSource.setPassword(password); dataSource.setPassword(password);
return dataSource; return dataSource;
} }
@Bean(name = "no2DataSourceSlave")
public DataSource no2DataSourceSlave() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(no2DataSourceSlaveDriver);
dataSource.setUrl(no2DataSourceSlaveUrl);
dataSource.setUsername(no2DataSourceSlaveUser);
dataSource.setPassword(no2DataSourceSlavePassword);
return dataSource;
}
@Bean(name = "no2TransactionManager") @Bean(name = "no2TransactionManager")
public DataSourceTransactionManager no2TransactionManager() { public DataSourceTransactionManager no2TransactionManager() {
return new DataSourceTransactionManager(no2DataSource()); return new DataSourceTransactionManager(no2DataSource());
} }
@Bean(name = "dynamicDataSourceNo2")
public DataSource dynamicDataSource(
@Qualifier("no2DataSource") DataSource no2DataSource,
@Qualifier("no2DataSourceSlave") DataSource no2DataSourceSlave) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> dataSourceMap = new HashMap<>();
dataSourceMap.put("no2DataSource", no2DataSource);
dataSourceMap.put("no2DataSourceSlave", no2DataSourceSlave);
dynamicDataSource.setTargetDataSources(dataSourceMap);
dynamicDataSource.setDefaultTargetDataSource(no2DataSource);
return dynamicDataSource;
}
@Bean(name = "no2SqlSessionFactory") @Bean(name = "no2SqlSessionFactory")
public SqlSessionFactory no2SqlSessionFactory(@Qualifier("no2DataSource") DataSource no2DataSource)throws Exception { public SqlSessionFactory no2SqlSessionFactory(@Qualifier("dynamicDataSourceNo2") DataSource dynamicDataSource)throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(no2DataSource); sessionFactory.setDataSource(dynamicDataSource);
// sessionFactory.setPlugins(new Interceptor[]{new SeparationN2Plugin()});
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(No2DataSourceConfig.MAPPER_LOCATION)); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(No2DataSourceConfig.MAPPER_LOCATION));
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(No2DataSourceConfig.CONFIG_LOCATION)); sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(No2DataSourceConfig.CONFIG_LOCATION));
sessionFactory.setTypeAliasesPackage(No2DataSourceConfig.TYPE_ALIASES_PACKAGE); sessionFactory.setTypeAliasesPackage(No2DataSourceConfig.TYPE_ALIASES_PACKAGE);
return sessionFactory.getObject(); return sessionFactory.getObject();
} }
} }

View File

@ -0,0 +1,22 @@
package com.zcloud.plugins;
/**
* TODO
* wangxuan
* www.zcloudchina.com
*/
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSourceType(String dataSourceType) {
contextHolder.set(dataSourceType);
}
public static String getDataSourceType() {
return contextHolder.get();
}
public static void clearDataSourceType() {
contextHolder.remove();
}
}

View File

@ -0,0 +1,15 @@
package com.zcloud.plugins;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
*
* wangxuan
* www.zcloudchina.com
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSourceType();
}
}

View File

@ -0,0 +1,75 @@
package com.zcloud.plugins;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import java.util.Properties;
/**
*
* luoxiaobao
* www.qdkjchina.com
*/
@Intercepts(
{
// @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class SeparationN1Plugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// if (invocation.getMethod().getName().equals("prepare")) {
// StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
// MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
// MappedStatement ms = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
// SqlCommandType sqlCommandType = ms.getSqlCommandType();
// if (sqlCommandType == SqlCommandType.SELECT) {
// DataSourceContextHolder.setDataSourceType("no2DataSourceSlave");
// }
// }
if (invocation.getMethod().getName().equals("query")) {
boolean isReadOnly = isReadOnlySql(invocation.getArgs());
if (isReadOnly) {
DataSourceContextHolder.setDataSourceType("no1DataSourceSlave");
} else {
DataSourceContextHolder.setDataSourceType("no1DataSource");
}
}
// return invocation.proceed();
// boolean isReadOnly = isReadOnlySql(invocation.getArgs());
// if (isReadOnly) {
// DataSourceContextHolder.setDataSourceType("no2DataSourceSlave");
// } else {
// DataSourceContextHolder.setDataSourceType("no2DataSource");
// }
try {
return invocation.proceed();
} finally {
DataSourceContextHolder.clearDataSourceType();
}
}
private boolean isReadOnlySql(Object[] args) {
// 获取 SQL 语句
MappedStatement ms = (MappedStatement) args[0];
SqlCommandType sqlCommandType = ms.getSqlCommandType();
// 判断是否为查询操作
return sqlCommandType == SqlCommandType.SELECT;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}

View File

@ -0,0 +1,79 @@
package com.zcloud.plugins;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import java.sql.Connection;
import java.util.Properties;
/**
*
* luoxiaobao
* www.qdkjchina.com
*/
@Intercepts(
{
// @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class SeparationN2Plugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// if (invocation.getMethod().getName().equals("prepare")) {
// StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
// MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
// MappedStatement ms = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
// SqlCommandType sqlCommandType = ms.getSqlCommandType();
// if (sqlCommandType == SqlCommandType.SELECT) {
// DataSourceContextHolder.setDataSourceType("no2DataSourceSlave");
// }
// }
if (invocation.getMethod().getName().equals("query")) {
boolean isReadOnly = isReadOnlySql(invocation.getArgs());
if (isReadOnly) {
DataSourceContextHolder.setDataSourceType("no2DataSourceSlave");
} else {
DataSourceContextHolder.setDataSourceType("no2DataSource");
}
}
// return invocation.proceed();
// boolean isReadOnly = isReadOnlySql(invocation.getArgs());
// if (isReadOnly) {
// DataSourceContextHolder.setDataSourceType("no2DataSourceSlave");
// } else {
// DataSourceContextHolder.setDataSourceType("no2DataSource");
// }
try {
return invocation.proceed();
} finally {
DataSourceContextHolder.clearDataSourceType();
}
}
private boolean isReadOnlySql(Object[] args) {
// 获取 SQL 语句
MappedStatement ms = (MappedStatement) args[0];
SqlCommandType sqlCommandType = ms.getSqlCommandType();
// 判断是否为查询操作
return sqlCommandType == SqlCommandType.SELECT;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}

View File

@ -1,5 +1,4 @@
#主库
datasource.no1.driver-class-name: com.mysql.cj.jdbc.Driver datasource.no1.driver-class-name: com.mysql.cj.jdbc.Driver
datasource.no1.url=jdbc:mysql://39.101.130.96:33068/qa-gwj-prevention?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf-8 datasource.no1.url=jdbc:mysql://39.101.130.96:33068/qa-gwj-prevention?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf-8
datasource.no1.username=root datasource.no1.username=root
@ -8,6 +7,16 @@ datasource.no2.driver-class-name: com.mysql.cj.jdbc.Driver
datasource.no2.url=jdbc:mysql://39.101.130.96:33068/qa-gwj-regulatory?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf-8 datasource.no2.url=jdbc:mysql://39.101.130.96:33068/qa-gwj-regulatory?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf-8
datasource.no2.username=root datasource.no2.username=root
datasource.no2.password=Mysql@zcloud88888 datasource.no2.password=Mysql@zcloud88888
#从库
datasource.slave.no1.driver-class-name: com.mysql.cj.jdbc.Driver
datasource.slave.no1.url=jdbc:mysql://192.168.0.17:3306/qa-gwj-prevention?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf-8
datasource.slave.no1.username=root
datasource.slave.no1.password=root
datasource.slave.no2.driver-class-name: com.mysql.cj.jdbc.Driver
datasource.slave.no2.url=jdbc:mysql://192.168.0.17:3306/qa-gwj-regulatory?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf-8
datasource.slave.no2.username=root
datasource.slave.no2.password=root
#druid??? #druid???

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD SQL Map Config 3.0//EN" <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD SQL Map Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration> <configuration>
@ -11,17 +11,18 @@
<typeAlias type="com.zcloud.entity.system.Role" alias="role"/> <typeAlias type="com.zcloud.entity.system.Role" alias="role"/>
<typeAlias type="com.zcloud.entity.system.Dictionaries" alias="dictionaries"/> <typeAlias type="com.zcloud.entity.system.Dictionaries" alias="dictionaries"/>
<typeAlias type="com.zcloud.entity.system.Department" alias="Department"/> <typeAlias type="com.zcloud.entity.system.Department" alias="Department"/>
<!-- 这里添加实体类 --> <!-- 这里添加实体类 -->
</typeAliases> </typeAliases>
<plugins> <plugins>
<plugin interceptor="com.zcloud.plugins.SeparationN1Plugin"/>
<plugin interceptor="com.zcloud.plugins.PagePlugin"> <plugin interceptor="com.zcloud.plugins.PagePlugin">
<property name="dialect" value="mysql"/> <property name="dialect" value="mysql"/>
<property name="pageSqlId" value=".*listPage.*"/> <property name="pageSqlId" value=".*listPage.*"/>
</plugin> </plugin>
</plugins> </plugins>
</configuration> </configuration>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD SQL Map Config 3.0//EN" <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD SQL Map Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration> <configuration>
@ -10,16 +10,18 @@
<typeAlias type="com.zcloud.entity.system.Menu" alias="menu"/> <typeAlias type="com.zcloud.entity.system.Menu" alias="menu"/>
<typeAlias type="com.zcloud.entity.system.Role" alias="role"/> <typeAlias type="com.zcloud.entity.system.Role" alias="role"/>
<typeAlias type="com.zcloud.entity.system.Dictionaries" alias="dictionaries"/> <typeAlias type="com.zcloud.entity.system.Dictionaries" alias="dictionaries"/>
<!-- 这里添加实体类 --> <!-- 这里添加实体类 -->
</typeAliases> </typeAliases>
<plugins> <plugins>
<plugin interceptor="com.zcloud.plugins.SeparationN2Plugin"/>
<plugin interceptor="com.zcloud.plugins.PagePlugin"> <plugin interceptor="com.zcloud.plugins.PagePlugin">
<property name="dialect" value="mysql"/> <property name="dialect" value="mysql"/>
<property name="pageSqlId" value=".*listPage.*"/> <property name="pageSqlId" value=".*listPage.*"/>
</plugin> </plugin>
</plugins> </plugins>
</configuration> </configuration>