application-test.properties

#datasource -- mysql
multiple.datasource.master.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
multiple.datasource.master.username=root
multiple.datasource.master.password=pypua
multiple.datasource.master.driverClassName=com.mysql.jdbc.Driver
multiple.datasource.master.InitialSize=10
multiple.datasource.master.MinIdle=10
multiple.datasource.master.MaxActive=100 multiple.datasource.slave.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
multiple.datasource.slave.username=root
multiple.datasource.slave.password=pypua
multiple.datasource.slave.driverClassName=com.mysql.jdbc.Driver
multiple.datasource.slave.InitialSize=10
multiple.datasource.slave.MinIdle=10
multiple.datasource.slave.MaxActive=100

创建核心枚举类型 (多个数据源的名称)DataSourceKey

package com.pupeiyuan.core;

public enum DataSourceKey {

     DB_MASTER,
DB_SLAVE1,
}

创建动态数据源DynamicRoutingDataSource,代表当前数据源

package com.pupeiyuan.core;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicRoutingDataSource extends AbstractRoutingDataSource{

    @Override
protected Object determineCurrentLookupKey() {
logger.info("当前数据源:{}"+ DynamicDataSourceContextHolder.get());
return DynamicDataSourceContextHolder.get();
} }

创建动态数据源上下文取值类 DynamicDataSourceContextHolder.java

package com.pupeiyuan.core;

import org.apache.log4j.Logger;

public class DynamicDataSourceContextHolder {

      private static final Logger LOG = Logger.getLogger(DynamicDataSourceContextHolder.class);
private static final ThreadLocal<DataSourceKey> currentDatesource = new ThreadLocal<>();
/**
* 清除当前数据源
*/
public static void clear() {
currentDatesource.remove();
} /**
* 获取当前使用的数据源
*
* @return 当前使用数据源的ID
*/
public static DataSourceKey get() {
return currentDatesource.get();
} /**
* 设置当前使用的数据源
*
* @param value 需要设置的数据源ID
*/
public static void set(DataSourceKey value) {
currentDatesource.set(value);
} /**
* 设置从从库读取数据
* 采用简单生成随机数的方式切换不同的从库
*/
/*public static void setSlave() {
if (RandomUtils.nextInt(0, 2) > 0) {
DynamicDataSourceContextHolder.set(DataSourceKey.DB_SLAVE2);
} else {
DynamicDataSourceContextHolder.set(DataSourceKey.DB_SLAVE1);
}
}*/
}

最主要的配置 mybatisConfig

package com.pupeiyuan.config;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager; import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.github.pagehelper.PageHelper;
import com.pupeiyuan.core.DataSourceKey;
import com.pupeiyuan.core.DynamicRoutingDataSource; import tk.mybatis.spring.annotation.MapperScan;
import tk.mybatis.spring.mapper.MapperScannerConfigurer; @Configuration
@MapperScan("com.pupeiyuan.mapper")
public class MyBatisConfig {
@Bean
//此处的"multiple.datasource.master"需要你在application.properties中配置,详细信息看下面贴出的application.properties文件。
@ConfigurationProperties(prefix = "multiple.datasource.master")
public DataSource dbMaster() {
DruidDataSource druidDataSource = DruidDataSourceBuilder.create().build();
//配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
try {
druidDataSource.setFilters("stat,wall,log4j");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // 通过connectProperties属性来打开mergeSql功能;慢SQL记录
druidDataSource.setConnectionProperties("druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000");
//合并多个DruidDataSource的监控数据
druidDataSource.setUseGlobalDataSourceStat(true);
return druidDataSource;
} @Bean
@ConfigurationProperties(prefix = "multiple.datasource.slave")
public DataSource dbSlave1() {
DruidDataSource druidDataSource = DruidDataSourceBuilder.create().build();
//配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
try {
druidDataSource.setFilters("stat,wall,log4j");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // 通过connectProperties属性来打开mergeSql功能;慢SQL记录
druidDataSource.setConnectionProperties("druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000");
//合并多个DruidDataSource的监控数据
druidDataSource.setUseGlobalDataSourceStat(true);
return druidDataSource;
}
/**
* 核心动态数据源
*
* @return 数据源实例
*/
@Bean
public DataSource dynamicDataSource() {
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
dataSource.setDefaultTargetDataSource(dbMaster());
Map<Object, Object> dataSourceMap = new HashMap<>(4);
dataSourceMap.put(DataSourceKey.DB_MASTER, dbMaster());
dataSourceMap.put(DataSourceKey.DB_SLAVE1, dbSlave1());
dataSource.setTargetDataSources(dataSourceMap);
return dataSource;
} @Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dynamicDataSource());
//此处设置为了解决找不到mapper文件的问题
//sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
return sqlSessionFactoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplate() throws Exception {
return new SqlSessionTemplate(sqlSessionFactory());
}
/**
* 事务管理
*
* @return 事务管理实例
*/
@Bean
public PlatformTransactionManager platformTransactionManager() {
return new DataSourceTransactionManager(dynamicDataSource());
} }

如果要配置自动切换数据源可以考虑AOP方式或者拦截器的方式进行配置,我这里采用手动切换

controller中手动切换

package com.pupeiyuan.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView; import com.github.pagehelper.PageHelper;
import com.pupeiyuan.bean.NhReportStatusHistory;
import com.pupeiyuan.common.controller.BaseController;
import com.pupeiyuan.core.DataSourceKey;
import com.pupeiyuan.core.DynamicDataSourceContextHolder;
import com.pupeiyuan.services.NhReportService;
/**
* @author pypua
* @date 2018年8月30日 上午9:21:20
*
*/
@Controller
@RequestMapping("burket")
@Scope("prototype")
public class BurketController extends BaseController { //services层注入
@Autowired NhReportService nhReportService; @RequestMapping(value = "/burketList", method = {RequestMethod.GET,RequestMethod.POST})
public ModelAndView burketList(HttpServletRequest request,
HttpServletResponse response
) throws Exception {
System.out.println("hello,springboot");
//参数容器
Map<String, Object> params = new HashMap<String, Object>();
PageHelper.startPage(1, 2);
DynamicDataSourceContextHolder.set(DataSourceKey.DB_SLAVE1);
List<NhReportStatusHistory> findList = nhReportService.findList(params);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("burketList");
modelAndView.addObject("list", findList);
return modelAndView;
} }

-----------------------------------------------亲测有效------------------------------------------------------

springboot动态多数据源切换的更多相关文章

  1. SpringBoot与动态多数据源切换

      本文简单的介绍一下基于SpringBoot框架动态多数据源切换的实现,采用主从配置的方式,配置master.slave两个数据库. 一.配置主从数据库 spring: datasource: ty ...

  2. springboot动态多数据源

    参考文章:https://www.cnblogs.com/hehehaha/p/6147096.html 前言 目标是springboot工程支持多个MySQL数据源,在代码层面上,同一个SQL(Ma ...

  3. springboot2.0动态多数据源切换

    摘要:springboot1.x到springboot2.0配置变化有一点变化,网上关于springboot2.0配置多数据源的资料也比较少,为了让大家配置多数据源从springboot1.x升级到s ...

  4. SpringBoot学习笔记:动态数据源切换

    SpringBoot学习笔记:动态数据源切换 数据源 Java的javax.sql.DataSource接口提供了一种处理数据库连接的标准方法.通常,DataSource使用URL和一些凭据来建立数据 ...

  5. SpringBoot之多数据源动态切换数据源

    原文:https://www.jianshu.com/p/cac4759b2684 实现 1.建库建表 首先,我们在本地新建三个数据库名分别为master,slave1,slave2,我们的目前就是写 ...

  6. Spring-Boot 多数据源配置+动态数据源切换+多数据源事物配置实现主从数据库存储分离

    一.基础介绍 多数据源字面意思,比如说二个数据库,甚至不同类型的数据库.在用SpringBoot开发项目时,随着业务量的扩大,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源. ...

  7. SpringBoot框架:通过AOP和自定义注解完成druid连接池的动态数据源切换(三)

    一.引入依赖 引入数据库连接池的依赖--druid和面向切面编程的依赖--aop,如下所示: <!-- druid --> <dependency> <groupId&g ...

  8. SpringBoot 动态切换多数据源

    1. 配置文件application-dev.properties 2. 动态切换数据源核心 A. 数据源注册器 B. 动态数据源适配器 C. 自定义注解 D. 动态数据源切面     E. 数据源路 ...

  9. 170714、springboot编程之多数据源切换(动态)

    (1)新建maven java project; 新建一个maven project,取名为:spring-boot-multi-ds (2)在pom.xml添加依赖包: 在pom.xml文件中加入依 ...

随机推荐

  1. Django实战(一)-----用户登录与注册系统2(数据模型、admin后台、路由视图)

    使用Django开发Web应用的过程中,很多人都是急急忙忙地写视图,写前端页面,把最根本的模型设计给忽略了. 模型中定义了数据如何在数据库内保存,再直白点说就是数据表的定义.这部分工作体现在Djang ...

  2. 使用ENCKEYS方法加密数据

    要使用这种数据加密方法,您需要配置Oracle GoldenGate以生成加密密钥并将密钥存储在本地ENCKEYS文件中.此方法使用的永久密钥只能通过根据使用加密密钥填充ENCKEYS文件中的说明重新 ...

  3. Python学习笔记-随机数

    IronPython的random 只能在0-0.5之间,所以最后调用了C#的Random. #!/usr/bin/python #coding=utf-8 import random import ...

  4. Effective C++ 笔记

    无参构造函数如何暴躁的构造. 先来看看标准的raw_memory : *sizeof(int)); // create int raw memory int *intVars = static_cas ...

  5. FAT文件系统规范v1.03学习笔记---2.FAT区之FAT数据结构(Fat Data Structure)

    1.前言 本文主要是对Microsoft Extensible Firmware Initiative FAT32 File System Specification中文翻译版的学习笔记. 每个FAT ...

  6. dubbo源码分析14——DubboProtocol的export方法分析

    走到了这一步也挺不容易的,把之前的暴露入口代码再列出来回顾一下: //配置为none不暴露 if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase ...

  7. vc++高级班之窗口篇[4]---让程序只运行一个实例

      大家都看过或者使用过类似只运行一个实例的程序,比如:QQ游戏.部分浏览器 等等! 让一个程序只运行一个实例的方法有多种,但是原理都类似,也就是在程序创建后,有窗口的程序在窗口创建前, 检查系统中是 ...

  8. 使用Let's Encrypt为网站加入SSL证书

    一直没有为网站配置过HTTPS,因为怕麻烦.不过这次工作要求,没有办法,只能硬着头皮上了. 老板提供了一个关键字,Let's Encrypt.其实最早看到这句话,我以为是一个动词,让我行动的意思.但是 ...

  9. P3830 [SHOI2012]随机树 题解

    P3830 随机树 坑题,别人的题解我看了一个下午没一个看得懂的,我还是太弱了. 题目链接 P3830 [SHOI2012]随机树 题目描述 输入输出格式 输入格式: 输入仅有一行,包含两个正整数 q ...

  10. 【ORIGINATE】详解

    originate 用法如下: originate <call url> <exten> |&<application_name>(<app_args ...