
控制於接口之上:
開始:demo地址 在lsr-core-base中
自定義注解:
/**
* @Description: 數據源切換注解
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DS {
DataSourceType value() default DataSourceType.db1;
}
數據源標識:
/**
* @Description: 數據源標識
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
public enum DataSourceType {
db1,db2
}
數據源配置setting:
/**
* @Description: 數據源配置
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
public class DruidSettings {
private String driverClassName;
private String url;
private String username;
private String password;
private String driverClassName2;
private String url2;
private String username2;
private String password2;
private int initialSize;
private int minIdle;
private int maxActive;
private long maxWait;
private long timeBetweenEvictionRunsMillis;
private long minEvictableIdleTimeMillis;
private String validationQuery;
private boolean testWhileIdle;
private boolean testOnBorrow;
private boolean testOnReturn;
private boolean poolPreparedStatements;
private String filters;
private int maxPoolPreparedStatementPerConnectionSize;
private boolean useGlobalDataSourceStat;
private String connectionProperties;
//get set
}
Druid配置類:
package cn.lsr.core.config.druid;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* = = Druid配置類
*
* @Version: 1.0
* @Author: Hacker_lsr@126.com
*/
@Configuration
public class DruidConfig {
@Autowired
DruidSettings druidSettings;
/**
* 數據源db1
* @return
*/
//@ConfigurationProperties(prefix = "spring.datasource.db1")
@Bean(name = "dataSource01")
public DataSource dataSource01(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(druidSettings.getDriverClassName());
druidDataSource.setUrl(druidSettings.getUrl());
druidDataSource.setUsername(druidSettings.getUsername());
druidDataSource.setPassword(druidSettings.getPassword());
druidDataSource.setInitialSize(druidSettings.getInitialSize());
druidDataSource.setMinIdle(druidSettings.getMinIdle());
druidDataSource.setMaxActive(druidSettings.getMaxActive());
druidDataSource.setMaxWait(druidSettings.getMaxWait());
druidDataSource.setTimeBetweenEvictionRunsMillis(druidSettings.getTimeBetweenEvictionRunsMillis());
druidDataSource.setMinEvictableIdleTimeMillis(druidSettings.getMinEvictableIdleTimeMillis());
druidDataSource.setValidationQuery(druidSettings.getValidationQuery());
druidDataSource.setTestWhileIdle(druidSettings.isTestWhileIdle());
druidDataSource.setTestOnBorrow(druidSettings.isTestOnBorrow());
druidDataSource.setTestOnReturn(druidSettings.isTestOnReturn());
druidDataSource.setPoolPreparedStatements(druidSettings.isPoolPreparedStatements());
try {
druidDataSource.setFilters(druidSettings.getFilters());
} catch (Exception e) {
e.printStackTrace();
}
druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(druidSettings.getMaxPoolPreparedStatementPerConnectionSize());
druidDataSource.setUseGlobalDataSourceStat(druidSettings.isUseGlobalDataSourceStat());
druidDataSource.setConnectionProperties(druidSettings.getConnectionProperties());
return druidDataSource;
}
/**
* 數據源db2
* @return
*/
//@ConfigurationProperties(prefix = "spring.datasource.db2")
@Bean(name = "dataSource02")
public DataSource dataSource02(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(druidSettings.getDriverClassName2());
druidDataSource.setUrl(druidSettings.getUrl2());
druidDataSource.setUsername(druidSettings.getUsername2());
druidDataSource.setPassword(druidSettings.getPassword2());
druidDataSource.setInitialSize(druidSettings.getInitialSize());
druidDataSource.setMinIdle(druidSettings.getMinIdle());
druidDataSource.setMaxActive(druidSettings.getMaxActive());
druidDataSource.setMaxWait(druidSettings.getMaxWait());
druidDataSource.setTimeBetweenEvictionRunsMillis(druidSettings.getTimeBetweenEvictionRunsMillis());
druidDataSource.setMinEvictableIdleTimeMillis(druidSettings.getMinEvictableIdleTimeMillis());
druidDataSource.setValidationQuery(druidSettings.getValidationQuery());
druidDataSource.setTestWhileIdle(druidSettings.isTestWhileIdle());
druidDataSource.setTestOnBorrow(druidSettings.isTestOnBorrow());
druidDataSource.setTestOnReturn(druidSettings.isTestOnReturn());
druidDataSource.setPoolPreparedStatements(druidSettings.isPoolPreparedStatements());
try {
druidDataSource.setFilters(druidSettings.getFilters());
} catch (Exception e) {
e.printStackTrace();
}
druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(druidSettings.getMaxPoolPreparedStatementPerConnectionSize());
druidDataSource.setUseGlobalDataSourceStat(druidSettings.isUseGlobalDataSourceStat());
druidDataSource.setConnectionProperties(druidSettings.getConnectionProperties());
return druidDataSource;
}
/**
* 動態數據源管理
* @return
*/
@Primary
@Bean(name = "dynamicDataSource")
public DataSource dynamicDataSource(){
DynamicDataSource dynamicDataSource = new DynamicDataSource();
//設置默認數據源
dynamicDataSource.setDefaultTargetDataSource(dataSource01());
Map<Object,Object> dbMap = new HashMap<>();
dbMap.put(DataSourceType.db1,dataSource01());
dbMap.put(DataSourceType.db2,dataSource02());
// targetDataSources 這里保存我們數據源配置的多個數據源)的數據源保存到resolvedDataSources
dynamicDataSource.setTargetDataSources(dbMap);
return dynamicDataSource;
}
/**
* 將動態數據源放入事務管理器
* @return
*/
@Bean
public PlatformTransactionManager transactionManager(){
return new DataSourceTransactionManager(dynamicDataSource());
}
/**
* 配置監控服務器
**/
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(
new StatViewServlet(), "/druid/*");
Map<String,String> initParams = new HashMap<>();
// druid后台管理員用戶
initParams.put("loginUsername","admin");
initParams.put("loginPassword","123456");
// 是否能夠重置數據
initParams.put("resetEnable", "false");
bean.setInitParameters(initParams);
return bean;
}
/**
* 配置web監控的過濾器
**/
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean(
new WebStatFilter());
// 添加過濾規則
bean.addUrlPatterns("/*");
Map<String,String> initParams = new HashMap<>();
// 忽略過濾格式
initParams.put("exclusions","*.js,*.css,*.icon,*.png,*.jpg,/druid/*");
bean.setInitParameters(initParams);
return bean;
}
}
動態數據源切換:
/**
* @Description: 動態數據源切換
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final Logger log = LoggerFactory.getLogger(DynamicDataSource.class);
// 當前線程數據源
private static final ThreadLocal<DataSourceType> dataSourceContext = new ThreadLocal<>();
@Override
protected Object determineCurrentLookupKey() {
log.info("數據源:{}",getDataSource());
return getDataSource();
}
/**
* 獲取當前數據源
* @return
*/
public DataSourceType getDataSource(){
return dataSourceContext.get();
}
/**
* 設置數據源
* @param dataSourceType
*/
public static void setDataSource(DataSourceType dataSourceType){
dataSourceContext.set(dataSourceType);
}
/**
* 刪除數據源
*/
public static void clearDataSource(){
dataSourceContext.remove();
}
}
注解動態數據源切換實現:
/**
* @Description: 動態數據源AOP
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
@Aspect
@Order(1)
@Component
public class DynamicDataSourceAspect {
@Before("@annotation(ds)")
public void beforeSwitchDS(JoinPoint joinPoint,DS ds){
//獲取當前訪問的class
Class<?> className = joinPoint.getTarget().getClass();
//獲取方法名
String methodName = joinPoint.getSignature().getName();
//獲取方法的參數類型
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
Class[] arrClass = methodSignature.getParameterTypes();
//默認數據源
DataSourceType dataSourceType = DataSourceType.db1;
try {
//得到方法對象
Method method = className.getMethod(methodName, arrClass);
//判斷是否有注解存在
if (method.isAnnotationPresent(DS.class)){
//拿到注解方法
DS dsValue = method.getAnnotation(DS.class);
//拿到注解value
dataSourceType = dsValue.value();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//切換數據源
DynamicDataSource.setDataSource(dataSourceType);
}
@After("@annotation(ds)")
public void afterSwitchDS(JoinPoint joinPoint,DS ds){
DynamicDataSource.clearDataSource();
}
}
application.properties##################################### 配置數據源 #####################################
##################################### 配置數據源 #####################################
datasource.db1url=192.168.0.104:3306/lsr-microservice
datasource.db2url=192.168.0.104:3306/lsr-microservice
##################################### 數據源1 #######################################
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://${datasource.db1url}?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=lishirui
##################################### 數據源2 #######################################
spring.datasource.driver-class-name2=com.mysql.jdbc.Driver
spring.datasource.url2=jdbc:mysql://${datasource.db1url}?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username2=root
spring.datasource.password2=lishirui
##################################### druid連接池 ###################################
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
spring.datasource.maxWait=60000
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
#配置監控統計攔截的filters.去掉后監控界面sql無法統計,'wall'用於防火牆
spring.datasource.filters=stat,wall,slf4j
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.useGlobalDataSourceStat=true
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
使用:@DS(DataSourceType.db1)
public interface UserMapper extends MyMapper<User> {
User selectByName(String username);
User selectUserByName(String username);
@DS(DataSourceType.db1)
User selecTest(String username);
}
