上文中http://blog.csdn.net/liunian02050328/article/details/75090297 讲述了springboot环境下读写分离的实现方法;
项目搭建的核心是为了给更多的用户去使用,部分情况下是使用读写分离,然后可以直接用这套框架,但是部分项目因业务量比较小,不想使用读写分离的方案呢?修改config?是的,这个方案看起来很不错,那么我们就坑次坑次的修改,修改好之后正常跑起来项目,看起来是一个不错的方案得到实施,过了几天后项目经理说,小X,根据项目的实际需求我们还是需要用到读写分离的方案,但是在本地开发的环境下只有master库,此时再次修改代码貌似不是一个良好的解决方案了;ok,那就看下下面的方案吧,下面的是个人观点及思路:
首先定义参数
readAndwriteKey: false #true false的时候代表的是不使用读写分离,true的时候是使用读写分离方案
通过参数配置,实现dev和relase环境的自由切换;
下面看下代码部分的修改;
在设计此方案的时候为第一放映想到的是@condition注解,貌似该注解是springframework4.x后出现的;之前貌似可以用别的方案实现;
采用注解的方式还是很不错的,最少直观易懂;
ok,开始看代码
首先定义个类实现condition方法,如下:
public class MasterCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String key=context.getEnvironment().getProperty("readAndwriteKey");
boolean flag="false".equals(key)? false:true;
return flag;
}
}
其中返回false的时候代表的是引用此处的@condition注解是不不加载到容器中来的;true的话就是相反了。
当为false的时候,在上一篇文章http://blog.csdn.net/liunian02050328/article/details/75090297中定义的路由就没什么用了。那么我们就用@condtion注解一下,如下
@Conditional(MasterCondition.class)
@Bean
public AbstractRoutingDataSource dataSouceProxy() {
MyAbstractRoutingDataSource proxy = new MyAbstractRoutingDataSource();
Map<Object, Object> targetDataSource = new HashMap<Object, Object>();
targetDataSource.put(DataSourceType.slaveDataSource.getDataSource(), slaveDataSource());
targetDataSource.put(DataSourceType.masterDataSource.getDataSource(), masterDataSource());
proxy.setTargetDataSources(targetDataSource);
proxy.setDefaultTargetDataSource(slaveDataSource());
return proxy;
}
相同的在上一篇定义的AOP的类上加上相同的注解即可。
此处的路由调度采用了condition注解,启动的时候没有加载到容器中来,在引用路由后获得的datasource时候获取为空,肯定会报异常,这时候需要修改方法sqlSessionFactory
具体修改如下:
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
boolean flag="false".equals(readAndwriteKey);
if (flag) {
sqlSessionFactoryBean.setDataSource(masterDataSource());
}else{
sqlSessionFactoryBean.setDataSource(dataSouceProxy());
}
// sqlSessionFactoryBean.setTypeAliasesPackage("com.*.*");
sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("/config/mybatis-config.xml"));
PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean
.setMapperLocations(resourcePatternResolver.getResources("classpath*:com/xx/xxx/mapper/*Mapper.xml"));
return sqlSessionFactoryBean.getObject();
}
上面的这个是不是可以改进下?我是采用的是if else 判断,是不是看起来比较low,欢迎高手指正并提出良好的解决方案
当我们根据数据源获得的sqlsessionfactory之后,ok,下面的就不永讲了,相信大家都会使用了。
总结如下:
所谓的读写分离,主要做的就是在数据连接底层切换数据源,如何切换呢?一主一从比较简单,这里的路由没怎么写路由算法,在一主多从的里面会涉及到,在后面的章节中会降到。
而设计读写分离的开关,无非就是屏蔽路由数据源的方法以及aop。