<connectionStrings>
<add name="test1" connectionString="server=127.0.0.1;user id=root;password=123456;database=db1;charset=utf8" providerName="MySql.Data.MySqlClient" />
<add name="test2" connectionString="server=127.0.0.1;user id=root;password=123456;database=db2;charset=utf8" providerName="MySql.Data.MySqlClient" />
<add name="test3" connectionString="server=127.0.0.1;user id=root;password=123456;database=db3;charset=utf8" providerName="MySql.Data.MySqlClient" />
<connectionStrings>

能不能像c#这样根据连接名称就自动选择呢,笔者的连接配置如下所示:

spring:
  application:
    name: csg-auth
  datasource:
    kbase:
     - driverClassName: com.kbase.jdbc.Driver
       jdbcUrl: jdbc:kbase://127.0.0.1
       username: DBOWN
       password:
    jdbc:
     - driverClassName: com.mysql.cj.jdbc.Driver
       jdbcUrl: jdbc:mysql://localhost:3306/nacos?serverTimezone=GMT%2B8&useUnicode=false&characterEncoding=utf8&useSSL=false
       username: root
       password: 123456
       connName: nacos
     - driverClassName: com.mysql.cj.jdbc.Driver
       jdbcUrl: jdbc:mysql://localhost:3306/tpi?serverTimezone=GMT%2B8&useUnicode=false&characterEncoding=utf8&useSSL=false
       username: root
       password: 123456
       connName: tpi

其中kbase不用理会,是我们公司自己的数据库,jdbc是维护的连接集合,其中connName就是我们自定义的连接名称,
根据connName就可以自动切换到对应数据源。

第一步

/**
 * 动态数据源
 * */
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return  DataSourceHolder.getDataSource();
    }
}

第二步

public class DataSourceHolder {
    /**
     * 线程本地环境
     */
    private static final ThreadLocal<String> dataSources = new ThreadLocal<String>();

    /**
     * 设置数据源
     */
    public static void setDataSources(String connName) {
        dataSources.set(connName);
    }

    /**
     * 获取数据源
     */
    public static String getDataSource() {
        return dataSources.get();
    }

    /**
     * 清楚数据源
     */
    public static void clearDataSource() {
        dataSources.remove();
    }
}

第三步

@Component
@ConfigurationProperties("spring.datasource")
public class DataSourceConfig {
    private List<DataSourceModel> jdbc;

    public Map<Object, Object> getDataSourceMap(){
        Map<Object, Object>map=new HashMap<>();
        if (jdbc!=null&&jdbc.size()>0){
            for (int i = 0; i < jdbc.size() ; i++) {
                DataSourceBuilder dataSourceBuilder=DataSourceBuilder.create();
                dataSourceBuilder.driverClassName(jdbc.get(i).getDriverClassName());
                dataSourceBuilder.password(jdbc.get(i).getPassword());
                dataSourceBuilder.username(jdbc.get(i).getUsername());
                dataSourceBuilder.url(jdbc.get(i).getJdbcUrl());
                map.put(jdbc.get(i).getConnName(),dataSourceBuilder.build());
            }
        }
        return map;
    }

    @Bean
    public DataSource csgDataSource(){
        DynamicDataSource dynamicDataSource=new DynamicDataSource();
        Map<Object,Object>dataSourceMap=getDataSourceMap();
        dynamicDataSource.setTargetDataSources(dataSourceMap);
         Object object= dataSourceMap.values().toArray()[0];
        dynamicDataSource.setDefaultTargetDataSource(object);
        return dynamicDataSource;
    }

    public void setJdbc(List<DataSourceModel> jdbc) {
        this.jdbc = jdbc;
    }

    public List<DataSourceModel> getJdbc(){
        return this.jdbc;
    }
}

第四部

@Configuration
public class MyBatisConfig {

    @Autowired
    private DataSource csgDataSource;

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean=new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(csgDataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/**/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public PlatformTransactionManager platformTransactionManager(){
        return new DataSourceTransactionManager(csgDataSource);
    }
}

第五步

/**
 * 注解标签
 * 作用于 方法、接口、类、枚举、注解
 * */

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface TargetDataSource {
    String connName();
}

第六步

@Aspect
@Component
public class DataSourceExchange {

    @Before("@annotation(TargetDataSource)")
    public void before(JoinPoint joinPoint){
        MethodSignature sign = (MethodSignature) joinPoint.getSignature();
        Method method = sign.getMethod();
        boolean isMethodAop= method.isAnnotationPresent(TargetDataSource.class);
        if (isMethodAop){
            TargetDataSource datasource = method.getAnnotation(TargetDataSource.class);
            DataSourceHolder.setDataSources(datasource.connName());
        }else {
            if (joinPoint.getTarget().getClass().isAnnotationPresent(TargetDataSource.class)){
                TargetDataSource datasource = joinPoint.getTarget().getClass().getAnnotation(TargetDataSource.class);
                DataSourceHolder.setDataSources(datasource.connName());
            }
        }
    }

    @After("@annotation(TargetDataSource)")
    public void after(){
        DataSourceHolder.clearDataSource();
    }
}

第七部

@Service
public class UserServiceImpl  implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    @TargetDataSource(connName = "nacos")
    public List<UserEntity> getList() {
        List<UserEntity> list= userMapper.selectUserList();
        return list;
    }
}

笔者从事java开发工作不多,改方法可能不是太好,也请各位看官勿喷~

11-21 19:10