☀️Terry

- - 草木逢春,雨过天晴🌈。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  36 随笔 :: 0 文章 :: 0 评论 :: 37966 阅读

 

控制于接口之上:

开始: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);
 
}

 

posted on 2020-02-27 20:55  ☀️Terry  阅读(985)  评论(0)    收藏  举报
编辑推荐:
· 从 Redis 客户端超时到 .NET 线程池挑战
· C23和C++26的#embed嵌入资源指南
· 「EF Core」框架是如何识别实体类的属性和主键的
· 独立开发,这条路可行吗?
· 我在厂里搞 wine 的日子
阅读排行:
· 他没买 iPad,而是花了半年时间,为所有“穷学生”写了个笔记神器
· Visual Studio 现已支持新的、更简洁的解决方案文件(slnx)格式
· 从 Redis 客户端超时到 .NET 线程池挑战:饥饿、窃取与阻塞的全景解析
· 2025年中总结:我想我克服公众演讲的恐惧了,一个社恐分子突破自我的故事
· 3.1k star!推荐一款开源基于AI实现的浏览器自动化插件工具 !
点击右上角即可分享
微信分享提示