天天看點

springboot 配置多資料源 good

1.首先在建立應用對象時引入autoConfig

package com;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}      

2.其次配置檔案

######primary#############  
datasource.primary.url=jdbc:sqlserver://xx.xx.xx.xx:1433;DatabaseName=PlayNowLog  
datasource.primary.username=sa  
datasource.primary.password=xxxxxx  
datasource.primary.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver  
  
  
######secondary#############  
datasource.secondary.url=jdbc:sqlserver://xx.xx.xx.xx:1433;DatabaseName=PlayNow_New  
datasource.secondary.username=sa  
datasource.secondary.password=xxxxxx  
datasource.secondary.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver      

3.再其次是資料源的建立

@Configuration  
public class GlobalDataConfiguration {  
    @Bean(name="primaryDataSource")  
    @Primary  
    @ConfigurationProperties(prefix="datasource.primary")  
    public DataSource primaryDataSource() {  
        System.out.println("-------------------- primaryDataSource init ---------------------");  
        return DataSourceBuilder.create().build();  
    }  
      
    @Bean(name="secondaryDataSource")  
    @ConfigurationProperties(prefix="datasource.secondary")  
    public DataSource secondaryDataSource() {  
        System.out.println("-------------------- secondaryDataSource init ---------------------");  
        return DataSourceBuilder.create().build();  
    }  
}      

4.Dao層使用資料源

@Component  
public class UserDaoImpl<T extends com.sonychina.backend.entity.statistic.SysUser> extends MyBatisBaseDao<SysUser> implements UserDao {  
      
    @Autowired  
    public UserDaoImpl(@Qualifier("secondaryDataSource") DataSource dataSource) {  
        super(dataSource);  
    }  
}      
import java.util.List;  
import java.util.Map;  
  
import javax.sql.DataSource;  
  
import org.apache.ibatis.session.SqlSession;  
  
import com.sonychina.backend.global.Constants;  
import com.sonychina.backend.utility.GenericsUtils;  
import com.sonychina.backend.utility.MapResultHandler;  
import com.sonychina.backend.utility.MyBatisUtil;  
import com.sonychina.backend.utility.PageView;  
  
public class MyBatisBaseDao<T>{  
    private Class<T> type;  
    private SqlSession session;  
      
    @SuppressWarnings("unchecked")  
    public MyBatisBaseDao(DataSource dataSource){  
        type = (Class<T>) GenericsUtils.getActualReflectArgumentClass(this.getClass());  
        System.out.println("------------- BaseMybatisDao initialize--------------------------");  
        System.out.println("------------- T:" + type.toString());  
        try {  
            MyBatisUtil myBatisUtil = MyBatisUtil.getInstance(dataSource);  
            session = myBatisUtil.getSession();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
      
      
    private String getMethodPath(String methodType){  
        return getMethodPath(methodType, "");  
    }  
      
    private String getMethodPath(String methodType, String methodSuffix){  
        return Constants.MYBATIS_MAPPER_PRIX + methodType + type.getSimpleName() + methodSuffix;  
    }  
      
    public void save(T obj) {  
        session.insert(getMethodPath("save"), obj);  
    }  
  
    public void delete(T obj) {  
        session.delete(getMethodPath("delete"), obj);  
    }  
  
    public void update(T obj) {  
        session.update(getMethodPath("update"), obj);  
        //HashMap<String,Object> map = null;  
    }  
  
    public T get(Integer id) {  
        return session.selectOne(getMethodPath("get"),id);  
    }  
      
    public List<T> getList(T entity){  
        return session.selectList(getMethodPath("get", "List"), entity);  
    }  
      
    public List<T> getListByAnyObject(Object entity){  
        return session.selectList(getMethodPath("get", "List"), entity);  
    }  
      
    /** 
     *  
     * @param entity 
     * @param selectId:mapper。xml檔案中<select>标簽ID 
     * @return 
     */  
    public List<T> getList(T entity, String selectId){  
        return session.selectList(selectId, entity);  
    }  
      
    public List<T> getListByAnyObject(Object entity, String selectId){  
        return session.selectList(selectId, entity);  
    }  
      
    public List<Map<String, Object>> getMapList(Map<String, Object> map){  
        MapResultHandler mh = new MapResultHandler();  
        session.select(getMethodPath("get", "MapList"), map, mh);  
        return mh.getMappedResults();  
    }  
      
    /** 
     *  
     * @param map 
     * @param selectId:mapper。xml檔案中<select>标簽ID 
     * @return List<Map<String, Object>> 
     */  
    public List<Map<String, Object>> getMapList(Map<String, Object> map, String selectId){  
        MapResultHandler mh = new MapResultHandler();  
        session.select(selectId, map, mh);  
        return mh.getMappedResults();  
    }  
      
    public List<Map<String, Object>> getMapList(T entity){  
        MapResultHandler mh = new MapResultHandler();  
        session.select(getMethodPath("get", "MapList"), entity, mh);  
        return mh.getMappedResults();  
    }  
  
    public List<Map<String, Object>> getMapList(T entity,String queryName){  
        MapResultHandler mh = new MapResultHandler();  
        session.select(queryName, entity, mh);  
        return mh.getMappedResults();  
    }  
  
    public Long getCount(Map<String, Object> pm){  
        MapResultHandler mh = new MapResultHandler();  
        session.select(getMethodPath("get", "Count"),pm, mh);  
        return mh.getCount();  
    }  
      
    /** 
     *  
     * @param pm 
     * @param selectId:mapper。xml檔案中<select>标簽ID 
     * @return Long 
     */  
    public Long getCount(Map<String,Object> pm, String selectId){  
        MapResultHandler mh = new MapResultHandler();  
        session.select(selectId,pm, mh);  
        return mh.getCount();  
    }  
      
    /** 
     * map 中必須包含 key:currentPageNum 且其值不能為空, 頁面顯示的記錄數不是10必須包含key:pageShowCnt 
     * 且其值不能為空 
     * @param map 
     * @return PageView 
     */  
    public PageView getPageList(Map<String, Object> map){  
          
        if(map == null || map.get("currentPageNum") == null){  
            return null;  
        } else{  
            PageView page = null;  
            Integer pageNum = Integer.valueOf(map.get("currentPageNum").toString());  
            if(map.get("pageShowCnt") == null){  
                page = new PageView(pageNum);  
            } else {  
                Integer showCnt = Integer.valueOf(map.get("pageShowCnt").toString());  
                page = new PageView(pageNum, showCnt);  
            }  
            map.put("start", page.getStart());  
            map.put("end", page.getCurrentMaxCnt());  
            //System.out.println("-----------start:" + map.get("start"));  
            //System.out.println("-----------start:" + map.get("maxCnt"));  
            MapResultHandler mh = new MapResultHandler();  
            page.setTotalRecord(this.getCount(map));  
            session.select(getMethodPath("get", "MapPageList"), map, mh);  
            page.setResultList(mh.getMappedResults());  
              
            return page;  
        }  
    }  
      
    /** 
     * map 中必須包含 key:currentPageNum 且其值不能為空, 頁面顯示的記錄數不是10必須包含key:pageShowCnt 
     * 且其值不能為空 
     * @param map 
     * @param selectConutId, mapper.xml檔案中<select>标簽Id, 查詢總記錄數的sql語句 
     * @param selectPageListId, mapper.xml檔案中<select>标簽Id,查詢分頁後資料清單的sql語句 
     * @return 
     */  
    public PageView getPageList(Map<String, Object> map, String selectConutId, String selectPageListId){  
          
        if(map == null || map.get("currentPageNum") == null){  
            return null;  
        } else{  
            PageView page = null;  
            Integer pageNum = Integer.valueOf(map.get("currentPageNum").toString());  
            if(map.get("pageShowCnt") == null){  
                page = new PageView(pageNum);  
            } else {  
                Integer showCnt = Integer.valueOf(map.get("pageShowCnt").toString());  
                page = new PageView(pageNum, showCnt);  
            }  
            map.put("start", page.getStart());  
            map.put("end", page.getCurrentMaxCnt());  
            //System.out.println("-----------start:" + map.get("start"));  
            //System.out.println("-----------start:" + map.get("maxCnt"));  
            MapResultHandler mh = new MapResultHandler();  
            page.setTotalRecord(this.getCount(map, selectConutId));  
            session.select(selectPageListId, map, mh);  
            page.setResultList(mh.getMappedResults());  
              
            return page;  
        }  
    }  
      
    /** 
     * map 中必須包含 key:currentPageNum 且其值不能為空, 頁面顯示的記錄數不是10必須包含key:pageShowCnt 
     * 且其值不能為空 
     * @param map 
     * @param selectConutId, mapper.xml檔案中<select>标簽Id, 查詢總記錄數的sql語句 
     * @param selectPageListId, mapper.xml檔案中<select>标簽Id,查詢分頁後資料清單的sql語句 
     * @return 
     */  
    public PageView getEntityPageList(Map<String, Object> map, String selectConutId, String selectPageListId){  
          
        if(map == null || map.get("currentPageNum") == null){  
            return null;  
        } else{  
            PageView page = null;  
            Integer pageNum = Integer.valueOf(map.get("currentPageNum").toString());  
            if(map.get("pageShowCnt") == null){  
                page = new PageView(pageNum);  
            } else {  
                Integer showCnt = Integer.valueOf(map.get("pageShowCnt").toString());  
                page = new PageView(pageNum, showCnt);  
            }  
            map.put("start", page.getStart());  
            map.put("end", page.getCurrentMaxCnt());  
            //System.out.println("-----------start:" + map.get("start"));  
            //System.out.println("-----------start:" + map.get("maxCnt"));  
            page.setTotalRecord(this.getCount(map, selectConutId));  
            page.setResultList(session.selectList(selectPageListId, map));  
              
            return page;  
        }  
    }  
      
    /** 
     * map 中必須包含 key:currentPageNum 且其值不能為空, 頁面顯示的記錄數不是10必須包含key:pageShowCnt 
     * 且其值不能為空 
     * @param map 
     * @return PageView 
     */  
    public PageView getEntityPageList(Map<String, Object> map){  
          
        if(map == null || map.get("currentPageNum") == null){  
            return null;  
        } else{  
            PageView page = null;  
            Integer pageNum = Integer.valueOf(map.get("currentPageNum").toString());  
            if(map.get("pageShowCnt") == null){  
                page = new PageView(pageNum);  
            } else {  
                Integer showCnt = Integer.valueOf(map.get("pageShowCnt").toString());  
                page = new PageView(pageNum, showCnt);  
            }  
            map.put("start", page.getStart());  
            map.put("end", page.getCurrentMaxCnt());  
            //System.out.println("-----------start:" + map.get("start"));  
            //System.out.println("-----------start:" + map.get("maxCnt"));  
            page.setTotalRecord(this.getCount(map));  
            page.setResultList(session.selectList(getMethodPath("get", "PageList"), map));  
              
            return page;  
        }  
    }  
}      

SpringBoot使用阿裡資料庫連接配接池Druid以及多資料源配置

引入依賴

<!-- https:dataSource
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.29</version>
</dependency>      

資料源配置

  • 1.資料源
#master資料源
spring.datasource.master.url=jdbc:mysql://localhost:3306/SpringBootMaster
spring.datasource.master.username=root
spring.datasource.master.password=1
spring.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.master.masterMapperLocations=classpath:mapper/master/*.xml


#cluster資料源
spring.datasource.cluster.url=jdbc:mysql://localhost:3306/SpringBootCluster
spring.datasource.cluster.username=root
spring.datasource.cluster.password=1
spring.datasource.cluster.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.cluster.clusterMapperLocations=classpath:mapper/cluster/*.xml


#cluster1資料源
spring.datasource.cluster1.url=jdbc:mysql://localhost:3306/SpringBootCluster1
spring.datasource.cluster1.username=root
spring.datasource.cluster1.password=1
spring.datasource.cluster1.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.cluster1.clusterMapperLocations=classpath:mapper/cluster1/*.xml      

master資料源:

@Configuration
@MapperScan(basePackages = {"com.lc.springBoot.druid.mapper.master"},
        sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDruidDataSourceConfig {

    @Value("${spring.datasource.master.masterMapperLocations}")
    private String masterMapperLocations;

    @ConfigurationProperties(prefix = "spring.datasource.master")
    @Bean(name = "masterDataSource")
    @Primary
    public DataSource masterDataSource() {
        return new DruidDataSource();
    }

    /**
     * SqlSessionFactory配置
     *
     * @return
     * @throws Exception
     */
    @Bean(name = "masterSqlSessionFactory")
    @Primary
    public SqlSessionFactory masterSqlSessionFactory(
            @Qualifier("masterDataSource") DataSource dataSource
    ) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);

        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 配置mapper檔案位置
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources(masterMapperLocations));

        //配置分頁插件
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        properties.setProperty("returnPageInfo", "check");
        properties.setProperty("params", "count=countSql");
        pageHelper.setProperties(properties);

        //設定插件
        sqlSessionFactoryBean.setPlugins(new Interceptor[]{pageHelper});
        return sqlSessionFactoryBean.getObject();
    }

    /**
     * 配置事物管理器
     *
     * @return
     */
    @Bean(name = "masterTransactionManager")
    @Primary
    public DataSourceTransactionManager masterTransactionManager(
            @Qualifier("masterDataSource") DataSource dataSource
    ) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}      

cluster資料源:

@Configuration
@MapperScan(basePackages = {"com.lc.springBoot.druid.mapper.cluster"},
        sqlSessionFactoryRef = "clusterSqlSessionFactory")
public class ClusterDruidDataSourceConfig {

    @Value("${spring.datasource.cluster.clusterMapperLocations}")
    private String clusterMapperLocations;

    @ConfigurationProperties(prefix = "spring.datasource.cluster")
    @Bean(name = "clusterDataSource")
    public DataSource clusterDataSource() {
        return new DruidDataSource();
    }

    /**
     * SqlSessionFactory配置
     *
     * @return
     * @throws Exception
     */
    @Bean(name = "clusterSqlSessionFactory")
    public SqlSessionFactory clusterSqlSessionFactory(
            @Qualifier("clusterDataSource") DataSource dataSource
    ) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);

        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        //配置mapper檔案位置
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources(clusterMapperLocations));

        //配置分頁插件
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        properties.setProperty("returnPageInfo", "check");
        properties.setProperty("params", "count=countSql");
        pageHelper.setProperties(properties);

        //設定插件
        sqlSessionFactoryBean.setPlugins(new Interceptor[]{pageHelper});
        return sqlSessionFactoryBean.getObject();
    }

    /**
     * 配置事物管理器
     *
     * @return
     */
    @Bean(name = "clusterTransactionManager")
    public DataSourceTransactionManager clusterTransactionManager(
            @Qualifier("clusterDataSource") DataSource dataSource
    ) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}      
  • cluster1資料源:
@Configuration
@MapperScan(basePackages = {"com.lc.springBoot.druid.mapper.cluster1"},
        sqlSessionFactoryRef = "cluster1SqlSessionFactory")
public class Cluster1DruidDataSourceConfig {

    @Value("${spring.datasource.cluster1.clusterMapperLocations}")
    private String cluster1MapperLocations;

    @ConfigurationProperties(prefix = "spring.datasource.cluster1")
    @Bean(name = "cluster1DataSource")
    public DataSource cluster1DataSource() {
        return new DruidDataSource();
    }

    /**
     * SqlSessionFactory配置
     *
     * @return
     * @throws Exception
     */
    @Bean(name = "cluster1SqlSessionFactory")
    public SqlSessionFactory cluster1SqlSessionFactory(
            @Qualifier("cluster1DataSource") DataSource dataSource
    ) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);

        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        //配置mapper檔案位置
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources(cluster1MapperLocations));

        //配置分頁插件
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        properties.setProperty("returnPageInfo", "check");
        properties.setProperty("params", "count=countSql");
        pageHelper.setProperties(properties);

        //設定插件
        sqlSessionFactoryBean.setPlugins(new Interceptor[]{pageHelper});
        return sqlSessionFactoryBean.getObject();
    }

    /**
     * 配置事物管理器
     *
     * @return
     */
    @Bean(name = "cluster1TransactionManager")
    public DataSourceTransactionManager cluster1TransactionManager(
            @Qualifier("cluster1DataSource") DataSource dataSource
    ) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}      
  • 2.相關注解說明

    @MapperScan:basePackages屬性配置需要掃描的mybatis的mapper檔案位置,sqlSessionFactory屬性配置具體的 sqlSessionFactory.

    @ConfigurationProperties:讀取并且設定我們在application.properties配置的内容.

    @Primary:這個注解用來辨別當存在多個相同的類型的bean時,優先選用哪個bean注入,需要注意的是,配置多資料源的時候,必須有一個 且隻能有一個@Primary注解.

讀寫分離實作

read資料源配置

```
@Configuration
@MapperScan(basePackages = {"com.lc.springBoot.druid.mapper.read1"},
        sqlSessionFactoryRef = "read1SqlSessionFactory")
public class Read1DruidDataSourceConfig {

    @Value("${spring.datasource.read1.read1MapperLocations}")
    private String read1MapperLocations;

    @ConfigurationProperties(prefix = "spring.datasource.read1")
    @Bean(name = "read1DataSource")
    public DataSource read1DataSource() {
        return new DruidDataSource();
    }

    /**
     * SqlSessionFactory配置
     *
     * @return
     * @throws Exception
     */
    @Bean(name = "read1SqlSessionFactory")
    public SqlSessionFactory read1SqlSessionFactory(
            @Qualifier("read1DataSource") DataSource dataSource
    ) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);

        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 配置mapper檔案位置
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources(read1MapperLocations));

        //配置分頁插件
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        properties.setProperty("returnPageInfo", "check");
        properties.setProperty("params", "count=countSql");
        pageHelper.setProperties(properties);

        //設定插件
        sqlSessionFactoryBean.setPlugins(new Interceptor[]{pageHelper});
        return sqlSessionFactoryBean.getObject();
    }

    /**
     * 配置事物管理器
     *
     * @return
     */
    @Bean(name = "read1TransactionManager")
    public DataSourceTransactionManager read1TransactionManager(
            @Qualifier("read1DataSource") DataSource dataSource
    ) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

```      

write資料源配置

```
@Configuration
@MapperScan(basePackages = {"com.lc.springBoot.druid.mapper.write"},
        sqlSessionFactoryRef = "writeSqlSessionFactory")
public class WriteDruidDataSourceConfig {

    @Value("${spring.datasource.write.writeMapperLocations}")
    private String writeMapperLocations;

    @ConfigurationProperties(prefix = "spring.datasource.write")
    @Bean(name = "writeDataSource")
    public DataSource writeDataSource() {
        return new DruidDataSource();
    }

    /**
     * SqlSessionFactory配置
     *
     * @return
     * @throws Exception
     */
    @Bean(name = "writeSqlSessionFactory")
    public SqlSessionFactory writeSqlSessionFactory(
            @Qualifier("writeDataSource") DataSource dataSource
    ) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);

        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 配置mapper檔案位置
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources(writeMapperLocations));
        return sqlSessionFactoryBean.getObject();
    }

    /**
     * 配置事物管理器
     *
     * @return
     */
    @Bean(name = "writeTransactionManager")
    public DataSourceTransactionManager writeTransactionManager(
            @Qualifier("writeDataSource") DataSource dataSource
    ) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}
```      

自定義注入AbstractRoutingDataSource

```
@Configuration
public class DataSourceConfig {

    private final static String WRITE_DATASOURCE_KEY = "writeDataSource";
    private final static String READ1_DATASOURCE_KEY = "read1DataSource";
    private final static String READ2_DATASOURCE_KEY = "read2DataSource";

    @Bean
    public AbstractRoutingDataSource routingDataSource(
            @Qualifier("writeDataSource") DataSource  writeDataSource,
            @Qualifier("read1DataSource") DataSource  read1DataSource,
            @Qualifier("read2DataSource") DataSource  read2DataSource
    ) {
        DynamicDataSource dataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap();
        targetDataSources.put(WRITE_DATASOURCE_KEY, writeDataSource);
        targetDataSources.put(READ1_DATASOURCE_KEY, read1DataSource);
        targetDataSources.put(READ2_DATASOURCE_KEY, read2DataSource);
        dataSource.setTargetDataSources(targetDataSources);
        dataSource.setDefaultTargetDataSource(writeDataSource);
        return dataSource;
    }
}
```      

自定義注解

```
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
    String dataSource() default "";//資料源
}

```      

使用ThreadLocal使資料源與線程綁定

```
public class DynamicDataSourceHolder {
    //使用ThreadLocal把資料源與目前線程綁定
    private static final ThreadLocal<String> dataSources = new ThreadLocal<String>();

    public static void setDataSource(String dataSourceName) {
        dataSources.set(dataSourceName);
    }

    public static String getDataSource() {
        return (String) dataSources.get();
    }

    public static void clearDataSource() {
        dataSources.remove();
    }
}
```
```
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {

        //可以做一個簡單的負載均衡政策
        String lookupKey = DynamicDataSourceHolder.getDataSource();
        System.out.println("------------lookupKey---------"+lookupKey);

        return lookupKey;
    }
}

```      

定義切面

```
@Aspect
@Component
public class DynamicDataSourceAspect {
    @Around("execution(public * com.lc.springBoot.druid.service..*.*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        Method targetMethod = methodSignature.getMethod();
        if (targetMethod.isAnnotationPresent(TargetDataSource.class)) {
            String targetDataSource = targetMethod.getAnnotation(TargetDataSource.class).dataSource();
            System.out.println("----------資料源是:" + targetDataSource + "------");
            DynamicDataSourceHolder.setDataSource(targetDataSource);
        }
        Object result = pjp.proceed();//執行方法
        DynamicDataSourceHolder.clearDataSource();

        return result;
    }
}

```      

注解使用

```
@Service
public class StudentService {

    @Autowired
    private StudentMapper studentMapper;

    @Transactional
    @TargetDataSource(dataSource = "writeDataSource")
    public boolean createUser(Student student) {
        studentMapper.insert(student);

        //事務測試
//        int i = 1 / 0;
        return true;
    }

    @TargetDataSource(dataSource = "read1DataSource")
    public List<Student> getByPage(int page, int rows) {
        Page<Student> studentPage = PageHelper.startPage(page, rows, true);
        List<Student> students = studentMapper.getBypage();
        System.out.println("-------------------" + studentPage.toString() + "-----------");
        return students;
    }
}

```      

druid監控功能配置

配置過濾器

```
/**
 * 配置過濾器,需要攔截哪些url,忽略哪些url,初始化參數等
 *
 * @author lsj <[email protected]>
 * @date 17-4-7
 */
@WebFilter(filterName = "druidStatFilter",//過濾器名稱
        urlPatterns = "/",//需要攔截的url
        initParams = {//filter初始化資訊
                //需要忽略的資源
                @WebInitParam(name = "exclusions", value = "*.js,*.gif,*.jpg," +
                        "*.bmp,*.png,*.css,*.ico,/druid/*"),
                @WebInitParam(name = "sessionStatEnable", value = "true"),
                @WebInitParam(name = "profileEnable", value = "true")})
public class DruidStatFilter extends WebStatFilter {
}

```      

配置servlet

//表明這是一個servlet
@WebServlet(urlPatterns = "/druid/*",//通過哪個url通路
        initParams = {
                @WebInitParam(name = "loginUsername", value = "lengchuan"),//使用者名
                @WebInitParam(name = "loginPassword", value = "123456"), //密碼
                @WebInitParam(name = "resetEnable", value = "true"),//是否可以重置
                // @WebInitParam(name = "allow",value = "127.0.0.1"),//白名單
                // @WebInitParam(name = "deny",value = "192.168.1.1")//黑名單
        })
public class DruidStatViewServlet extends StatViewServlet {
}      

配置Spring監控

@Configuration
public class MyDruidStatInterceptor {

    private static final String[] patterns = new String[]{"com.lc.springBoot.druid.service.*"};

    @Bean
    public DruidStatInterceptor druidStatInterceptor() {
        return new DruidStatInterceptor();
    }

    /**
     * 切入點
     * @return
     */
    @Bean
    public JdkRegexpMethodPointcut druidStatPointcut() {
        JdkRegexpMethodPointcut druidStatPointcut = new JdkRegexpMethodPointcut();
        druidStatPointcut.setPatterns(patterns);
        return druidStatPointcut;
    }

    /**
     * 配置aop
     * @return
     */
    @Bean
    public Advisor druidStatAdvisor() {
        return new DefaultPointcutAdvisor(druidStatPointcut(), druidStatInterceptor());
    }
}      

通路監控頁面

配置完成後啟動項目,通路loccalhost:8080/druid/就可以看到我們的監控頁面了,使用者名配置的是lengchuan,密碼是123456這裡需要注意的是,我們隻有在
執行了一次資料庫操作後,才能擷取到我們的資料源資訊.      

​​https://github.com/Lengchuan/SpringBoot-Study/tree/master/SpringBoot-Druid​​