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