application-test.properties
#datasource -- mysqlmultiple.datasource.master.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=truemultiple.datasource.master.username=rootmultiple.datasource.master.password=pypuamultiple.datasource.master.driverClassName=com.mysql.jdbc.Drivermultiple.datasource.master.InitialSize=10multiple.datasource.master.MinIdle=10multiple.datasource.master.MaxActive=100multiple.datasource.slave.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=truemultiple.datasource.slave.username=rootmultiple.datasource.slave.password=pypuamultiple.datasource.slave.driverClassName=com.mysql.jdbc.Drivermultiple.datasource.slave.InitialSize=10multiple.datasource.slave.MinIdle=10multiple.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 ThreadLocalcurrentDatesource = 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
如果要配置自动切换数据源可以考虑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"); //参数容器 Mapparams = new HashMap (); PageHelper.startPage(1, 2); DynamicDataSourceContextHolder.set(DataSourceKey.DB_SLAVE1); List findList = nhReportService.findList(params); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("burketList"); modelAndView.addObject("list", findList); return modelAndView; } }
-----------------------------------------------亲测有效------------------------------------------------------