控制於接口之上:
開始: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); }