当前位置: 移动技术网 > IT编程>开发语言>Java > Spring配置动态数据源实现读写分离的方法

Spring配置动态数据源实现读写分离的方法

2019年07月22日  | 移动技术网IT编程  | 我要评论

前言

最近因为工作的需要,要搭建的一个项目需要实现数据源的读写分离,在这里将代码进行分享,有需要的朋友们可以参考学习。

首先是配置数据源

<!--读数据源配置-->
<bean id="readdatasource" class="com.alibaba.druid.pool.druiddatasource" init-method="init"destroy-method="close">
//配置省略
</bean>

<!--写数据源配置-->
<bean id="writedatasource" class="com.alibaba.druid.pool.druiddatasource" init-method="init"destroy-method="close">
//配置省略
</bean>

<!-- 动态数据源 -->
<bean id = "datasource" class="com.potato.common.bean.dynamicdatasource" > 
 <!-- 已配置的数据源 --> 
 <property name="targetdatasources">  
 <map>   
  <entry key="read" value-ref="readdatasource"/>   
  <entry key="write" value-ref="writedatasource"/>  
 </map> 
 </property> 
 <!-- 默认的数据源 --> 
 <property name="defaulttargetdatasource" ref="writedatasource"/>
</bean>

数据源是如何切换的呢?通过动态数据源的配置我们知道原来是通过key来进行切换,这里要使用到org.springframework.jdbc.datasource.lookup.abstractroutingdatasource,我们可以编写自己的动态数据源类dynamicdatasource来继承它。

public class dynamicdatasource extends abstractroutingdatasource { 
 @override 
 protected object determinecurrentlookupkey() {  
  return datasourcecontextholder.gettype(); 
 }
}

还需要一个存放key的地方datasourcecontextholder 为保证切换时线程安全我们使用threadlocal来保存我们的key。

public class datasourcecontextholder {
 private static final logger logger = loggerfactory.getlogger(datasourcecontextholder.class);
 public static final string data_source_write = "write";
 public static final string data_source_read = "read";
 // 线程本地环境
 private static final threadlocal<string> contextholder = new threadlocal<string>();

 // 设置数据源类型
 public static void settype(string type) {
  if(logger.isdebugenabled())
   logger.debug("==============切换数据源,类型:"+type+"================");
  contextholder.set(type);
 }
 // 获取数据源类型
 public static string gettype() {
  return (contextholder.get());
 }
 // 清除数据源类型
 public static void cleartype() {
  contextholder.remove();
 }
}

好了,我们可以通过操作datasourcecontextholder来实现数据源动态的切换了。小伙伴们可能会说了,难道每次调用方法都要手动选择要切换的数据源类型?当然不是啦,spring aop登场。

@component
@aspect
public class dynamicdatasourceaspect {

 @pointcut("execution (* com.potato.orm.mapper.*.select*(..)) || execution (* com.potato.orm.mapper.*.count*(..)) ")
 public void readmethodpointcut() {}

 @pointcut("execution (* com.potato.orm.mapper.*.insert*(..)) || execution (* com.potato.orm.mapper.*.update*(..)) || execution (* com.potato.orm.mapper.*.delete*(..))")
 public void writemethodpointcut() {}

 @before("readmethodpointcut()")
 public void switchreaddatasource(){
  //system.out.println("============切换到读数据源===========");
  datasourcecontextholder.settype(datasourcecontextholder.data_source_read);
 }

 @before("writemethodpointcut()")
 public void switchwritedatasource(){
  //system.out.println("=============切换到写数据源==========");
  datasourcecontextholder.settype(datasourcecontextholder.data_source_write);
 }

}

总结

好啦,以上就是这篇文章的全部内容了,在访问mapper(本项目使用的是mybatis啦,相当于是dao)中查询方法时会切换到读数据源,增、删、改方法会切换到写数据源。希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网