zoukankan      html  css  js  c++  java
  • springboot+mysql数据源切换

    数据源切换

    一.这 里我做的是mysql读写分离,我是建立了两个链接,分别用了不同的端口号来分开(当然也可以区分数据库,这个根据自己所需 )

     

    spring.datasource.select.jdbc-url=jdbc:mysql://localhost:3308/product
    spring.datasource.select.username=root
    spring.datasource.select.password=
    spring.datasource.select.driver-class-name=com.mysql.jdbc.Driver
    
    
    spring.datasource.update.jdbc-url=jdbc:mysql://localhost:3307/product
    spring.datasource.update.username=root
    spring.datasource.update.password=
    spring.datasource.update.driver-class-name=com.mysql.jdbc.Driver
    #加载mapper文件
    mybatis.mapper-locations=classpath*:mapper/*.xml
    #修改访问端口
    server.port=8099

     

    这个是在springboot项目中的,application.properties文件中连接的

    二.接下来我们添加工具包

    package com.fh.datademo.datasoucedynamic;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import javax.sql.DataSource;
    
    /**
     * @author yuchunqiang
     * @Title: DataSourceConfig
     * @Package com.fh.datademo.datasoucedynamic
     * @Description: ${todo}
     * @date 2018/10/24  16:01
     */
    @Configuration
    public class DataSourceConfig {
        @Bean(name = "selectDataSource")
        @ConfigurationProperties(prefix = "spring.datasource.select")
        public DataSource dataSource1() {
            return DataSourceBuilder.create().build();
        }
    
        @Bean(name = "updateDataSource")
        @ConfigurationProperties(prefix = "spring.datasource.update")
        public DataSource dataSource2() {
            return DataSourceBuilder.create().build();
        }
    
    }

    这个主要用来找到两个mysql的连接,并提供给另外一个工具包决定我们的方法到底走application.properties中哪一个连接

     1 package com.fh.datademo.datasoucedynamic;
     2 
     3 import org.springframework.context.annotation.Lazy;
     4 import org.springframework.stereotype.Component;
     5 
     6 /**
     7  * @author yuchunqiang
     8  * @Title: DataSourceContextHolder
     9  * @Package com.fh.datademo.datasoucedynamic
    10  * @Description: ${todo}
    11  * @date 2018/10/24  16:00
    12  */
    13 @Component
    14 @Lazy(false)
    15 public class DataSourceContextHolder {
    16     private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    17 
    18     public static void setDbType(String dbType) {
    19         contextHolder.set(dbType);
    20     }
    21 
    22     public static String getDbType() {
    23         return contextHolder.get();
    24     }
    25 
    26     public static void clearDbType() {
    27         contextHolder.remove();
    28     }
    29 }
     1 package com.fh.datademo.datasoucedynamic;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.beans.factory.annotation.Qualifier;
     5 import org.springframework.context.annotation.Primary;
     6 import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
     7 import org.springframework.stereotype.Component;
     8 
     9 
    10 import javax.sql.DataSource;
    11 import java.util.HashMap;
    12 import java.util.Map;
    13 
    14 /**
    15  * @author yuchunqiang
    16  * @Title: DynamicDataSource
    17  * @Package com.fh.datademo.datasoucedynamic
    18  * @Description: ${todo}
    19  * @date 2018/10/24  16:06
    20  */
    21 @Component
    22 @Primary
    23 public class DynamicDataSource extends AbstractRoutingDataSource {
    24 
    25     @Autowired
    26     @Qualifier("selectDataSource")
    27     private DataSource selectDataSource;
    28 
    29     @Autowired
    30     @Qualifier("updateDataSource")
    31     private DataSource updateDataSource;
    32 
    33     /**
    34      * 这个是主要的方法,返回的是生效的数据源名称
    35      */
    36     @Override
    37     protected Object determineCurrentLookupKey() {
    38         System.out.println("DataSourceContextHolder:::"+DataSourceContextHolder.getDbType());
    39         return DataSourceContextHolder.getDbType();
    40     }
    41 
    42     /**
    43      * 自己配的时候老是报什么没有指定target这里设置一下,默认数据源是updateDataSource
    44      */
    45     @Override
    46     public void afterPropertiesSet() {
    47         Map<Object,Object> map = new HashMap<>();
    48         map.put("selectDataSource",selectDataSource);
    49         map.put("updateDataSource",updateDataSource);
    50         setTargetDataSources(map);
    51         setDefaultTargetDataSource(updateDataSource);
    52         super.afterPropertiesSet();
    53     }
    54 }
     1 package com.fh.datademo.datasoucedynamic;
     2 
     3 import org.aspectj.lang.JoinPoint;
     4 import org.aspectj.lang.annotation.Aspect;
     5 import org.aspectj.lang.annotation.Before;
     6 import org.springframework.context.annotation.Lazy;
     7 import org.springframework.core.annotation.Order;
     8 import org.springframework.stereotype.Component;
     9 
    10 /**
    11  * @author yuchunqiang
    12  * @Title: SwitchDataSourceAOP
    13  * @Package com.fh.datademo.datasoucedynamic
    14  * @Description: ${todo}
    15  * @date 2018/10/24  15:54
    16  */
    17 @Aspect
    18 @Component
    19 @Lazy(false)
    20 @Order(0) //Order设定AOP执行顺序 使之在数据库事务上先执行
    21 public class SwitchDataSourceAOP {
    22 
    23     //这里切到你的方法目录
    24     @Before("execution(* com.fh.datademo.service.*.*.*(..))")
    25     public void process(JoinPoint joinPoint) {
    26         String methodName=joinPoint.getSignature().getName();
    27         if (methodName.startsWith("get")
    28                 ||methodName.startsWith("count")
    29                 ||methodName.startsWith("find")
    30                 ||methodName.startsWith("list")
    31                 ||methodName.startsWith("select")
    32                 ||methodName.startsWith("check")
    33                 ||methodName.startsWith("query")){
    34             DataSourceContextHolder.setDbType("selectDataSource");
    35         }else {
    36             //切换dataSource
    37             DataSourceContextHolder.setDbType("updateDataSource");
    38         }
    39     }
    40 
    41 }

    用来在走方法之前,来决定走哪个数据源,在@Before的设置中(@Before("execution(* com.fh.datademo.service.*.*.*(..))"))决定具体到哪个包,具体到哪个类,然后获取其方法名来判断,方法名中包含所规定的字符,则走读的数据源,否则走写的数据源。从而来达到读写分离,实现自动切换的功能

    项目git地址:https://github.com/yuchunqiang

  • 相关阅读:
    UVA 11525 好大好大的排列(线段树)
    UVA 11525 好大好大的排列(线段树)
    UVALive 4108城市天际线,混杂着递归与非递归的线段树
    UVALive 4108城市天际线,混杂着递归与非递归的线段树
    zencart搜索结果页面静态化 advanced_search_result
    .htaccess 一段神奇的跳转代码
    清除zencart分类页多页后面的&disp_order &sort字符串的方法
    zencart只有购买过此产品的客户才能评价产品
    mysql自增字段AUTO_INCREMENT重排或归零
    mysql语句修改zencart产品原价为特价的倍数
  • 原文地址:https://www.cnblogs.com/ycq-qiang/p/11340574.html
Copyright © 2011-2022 走看看