上文中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。