控制于接口之上:
开始:demo地址 在lsr-core-base中
自定义注解:
1 2 3 4 5 6 7 8 9 10 | /** * @Description: 数据源切换注解 * @Package: lsr-microservice * @author: Hacker_lsr@126.com **/ @Target (ElementType.METHOD) @Retention (RetentionPolicy.RUNTIME) public @interface DS { DataSourceType value() default DataSourceType.db1; } |
数据源标识:
1 2 3 4 5 6 7 8 | /** * @Description: 数据源标识 * @Package: lsr-microservice * @author: Hacker_lsr@126.com **/ public enum DataSourceType { db1,db2 } |
数据源配置setting:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | /** * @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配置类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | 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; } } |
动态数据源切换:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /** * @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(); } } |
注解动态数据源切换实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | /** * @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)
1 2 3 4 5 6 7 8 9 | public interface UserMapper extends MyMapper<User> { User selectByName(String username); User selectUserByName(String username); @DS (DataSourceType.db1) User selecTest(String username); } |
分类:
SpringBoot
【推荐】2025 HarmonyOS 鸿蒙创新赛正式启动,百万大奖等你挑战
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】开源 Linux 服务器运维管理面板 1Panel V2 版本正式发布
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 Redis 客户端超时到 .NET 线程池挑战
· C23和C++26的#embed嵌入资源指南
· 「EF Core」框架是如何识别实体类的属性和主键的
· 独立开发,这条路可行吗?
· 我在厂里搞 wine 的日子
· 他没买 iPad,而是花了半年时间,为所有“穷学生”写了个笔记神器
· Visual Studio 现已支持新的、更简洁的解决方案文件(slnx)格式
· 从 Redis 客户端超时到 .NET 线程池挑战:饥饿、窃取与阻塞的全景解析
· 2025年中总结:我想我克服公众演讲的恐惧了,一个社恐分子突破自我的故事
· 3.1k star!推荐一款开源基于AI实现的浏览器自动化插件工具 !