org.mybatis
mybatis
3.2.1
org.projectlombok lombok 1.16.16
mysql mysql-connector-java 5.1.26 com.alibaba druid 1.0.12
org.mybatis mybatis-spring 1.3.1 org.yaml snakeyaml 1.17
@Configuration @EnableTransactionManagement public class MultiDataSource { @Bean public DynamicDataSource dynamicDataSource() { DynamicDataSource source = new DynamicDataSource(); return source; } @Bean public SqlSessionFactoryBean sqlSessionFactoryBean(DynamicDataSource source) { ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean(); Resource[] resources ; try { resources = resolver.getResources("classpath*:META-INF/sqlmap/*Mapper.xml"); sqlSessionFactory.setDataSource(source); sqlSessionFactory.setMapperLocations(resources); } catch (IOException e) { e.printStackTrace(); } return sqlSessionFactory; } @Bean public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer configurer = new MapperScannerConfigurer(); configurer.setBasePackage("com.fulihui.welfarecentre.dal.mapper"); configurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean"); return configurer; } }
初始化 mybatis相关配置
public class DataSourceContextHolder { private static final ThreadLocal线程安全的TheadLocal来储存keycontextHolder = new ThreadLocal (); public static void setDataSource(String datasourceType){ contextHolder.set(datasourceType); } public static String getDataSource(){ return ((String) contextHolder.get()); } public static void clear(){ contextHolder.remove(); } }
@Data public class CustomDruidDataSource extends DruidDataSource { private static final long serialVersionUID = 7144084830980132474L; private String key; }定义一个对象 继承阿里巴巴的druiDataSource
@Data public class DataSourcesConfig { private List因为是多个数据源 所以又创建了一个对象 来顶一个list来接收 自定义的数据源dataSource; }
下面来实现 dubbo服务和 web工程拿到的传来的key
1、 dubbo服务:
@Activate(group = Constants.PROVIDER) public class DubboContextFilter implements Filter { private final Logger logger = LoggerFactory.getLogger(DubboContextFilter.class); @Override public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException { Object[] arguments = invocation.getArguments(); if(arguments != null && arguments.length > 0){ for (Object argument : arguments) { if(argument instanceof CommonRequest){ checkArgs(((CommonRequest) argument).getShowModule()); }else if(argument instanceof CommonPageRequest){ checkArgs(((CommonPageRequest) argument).getShowModule()); } break; } } return invoker.invoke(invocation); } /** * 参数校验 * @param platformSource */ private void checkArgs(Integer platformSource){ logger.info("dubbo context filter: platformSource={}",platformSource); if(platformSource == null){ throw new RpcException("platformSource can't be empty!"); } DataSourceContextHolder.setDataSource(platformSource.toString()); } }
在resources目录下添加纯文本文件META-INF/dubbo/com.alibaba.dubbo.rpc.Filter,内容如下:
dubboContextFilter=xx.xx.DubboContextFilter2:web工程
使用一个动态代理,在执行这个方法的时候,我们动态的给DataSourceContextHolder设置值,我建议使用spring aop,或者如果
不是spring的项目,那么直接只用动态代理也是很好的我觉,下面贴出核心代码
@Aspect
@Component
public class DataSourceAspect {
@Pointcut("execution(* com.wang.route.DynamicPersonService.*(..))")
public void pointCut() {
}
@Before(value = "pointCut()")
public void before(JoinPoint joinPoint) {
DataSourceContextHolder.setDataSource(platformSource.toString());}} 切换动态数据源 核心配置:
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { String dataSource = DataSourceContextHolder.getDataSource(); if (StringUtil.isBlank(dataSource)) { logger.info("determineCurrentLookupKey: dataSource not found!"); throw new RuntimeException("determineCurrentLookupKey: dataSource not found!"); } return DataSourceContextHolder.getDataSource(); } @Override public void afterPropertiesSet() { DataSourcesConfig config = null; Yaml yaml = new Yaml(); try { config = yaml.loadAs(new FileInputStream(new File("conf/dataSource.yml")), DataSourcesConfig.class); } catch (FileNotFoundException e) { e.printStackTrace(); } if (!Objects.isNull(config)) { Map
dataSource: - driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://192.168.1.45:3306/welfare username: root password: root1234 initialSize: 1 minIdle: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 'x' testWhileIdle: true testOnBorrow: false poolPreparedStatements: false maxPoolPreparedStatementPerConnectionSize: 50 filters: stat defaultAutoCommit: true key: 0 - driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://192.168.1.45:3306/welfare_1 username: root password: root1234 initialSize: 1 minIdle: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 'x' testWhileIdle: true testOnBorrow: false poolPreparedStatements: false maxPoolPreparedStatementPerConnectionSize: 50 filters: stat defaultAutoCommit: true key: 1