ssm读写分离多数据源

实现读写分离的方法
第一种:使用读写分离中间插件,实现读写分离,一般大公司会自己开发自己的中间件,中小型公司更多的是使用程序实现读写分离,中间件就不多介绍了。
第二种:就是在程序的读写分离,实现AbstractRoutingDataSource类的determineCurrentLookupKey方法

原理:借助spring的【org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource】这个抽象类实现。
每次去连数据库的时候,spring会调用determineCurrentLookupKey();这个方法去找对应的数据源。返回值即对应的数据源
/**
 * Determine the current lookup key. This will typically be
 * implemented to check a thread-bound transaction context.
 * <p>Allows for arbitrary keys. The returned key needs
 * to match the stored lookup key type, as resolved by the
 * {@link #resolveSpecifiedLookupKey} method.
 */
protected abstract Object determineCurrentLookupKey();

第一步,配置spring-dao.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:mvc="http://www.springframework.org/schema/mvc" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
   	    http://www.springframework.org/schema/beans
   	    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
   	    http://www.springframework.org/schema/mvc
    	http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
        
        <!-- 加载数据库配置文件和其他配置文件 -->
        <context:property-placeholder location="classpath:database.properties"/>
        
        <!-- 数据库连接池
        <bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource"
        destroy-method="close">
         	<property name="url" value="${jdbc.url}"></property>
         	<property name="username" value="${jdbc.username}"></property>
         	<property name="password" value="${jdbc.password}"></property>
         	<property name="driverClassName" value="${jdbc.driver}"></property>
       		<property name="minIdle" value="20"></property>
         </bean> -->
         
          <!-- 数据库连接池com.alibaba.druid.pool.DruidDataSource -->
        <bean id="masterdataSource" class="com.alibaba.druid.pool.DruidDataSource"
        destroy-method="close">
         	<property name="url" value="${jdbc.url}"></property>
         	<property name="username" value="${jdbc.username}"></property>
         	<property name="password" value="${jdbc.password}"></property>
         	<property name="driverClassName" value="${jdbc.driver}"></property>
         	<property name="maxActive" value="100"></property>
         	<property name="minIdle" value="20"></property>
         </bean>
         <!-- 读库 -->
         <bean id="slavedataSource" class="com.alibaba.druid.pool.DruidDataSource"
        destroy-method="close">
         	<property name="url" value="${jdbc.r.url}"></property>
         	<property name="username" value="${jdbc.r.username}"></property>
         	<property name="password" value="${jdbc.r.password}"></property>
         	<property name="driverClassName" value="${jdbc.r.driver}"></property>
         	<property name="maxActive" value="100"></property>
         	<property name="minIdle" value="20"></property>
         </bean>
         
         <!-- 动态数据源 -->
    <bean id="dynamicDataSource" class="com.tongzuwang.datasource.DynamicDataSource">
        <!-- 通过key-value关联数据源 -->
        <property name="targetDataSources">
            <map>
                <entry value-ref="masterdataSource" key="masterdataSource"></entry>
                <entry value-ref="slavedataSource" key="slavedataSource"></entry>
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="masterdataSource" />    
    </bean>
         
         
         <!-- 整合mybatis: SqlsessionFactory -->
         <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
         	<!-- 数据源 -->
         	<property name="dataSource" ref="dynamicDataSource"></property>
         	<!-- mybatis配置文件 -->
         	<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
         </bean>
         
         <!-- 注入DAO对象:配置mapper MapperFactoryBean:用于生成mapper代理对象 -->
		<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
			<!-- 配置扫描包的路径,如果要扫描多个包,中间使用逗号隔开 -->
			<property name="basePackage" value="com.tongzuwang.able"></property>
			<!-- 使用sqlSessionFactoryBeanName -->
			<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
		</bean>
</beans>

第二步,先继承AbstractRoutingDataSource 类实现determineCurrentLookupKey方法。

package com.tongzuwang.datasource;


import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {

    /**
     * 
     * override determineCurrentLookupKey
     * Title: determineCurrentLookupKey
     * Description: 自动查找datasource
     * 
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return DBContextHolder.getDbType();
    }
 
}


这个方法要返回的值。那么如何设置,让这个方法的返回值是根据我们的需要返回dataSource由于这个方法没有入参,并且是spring自动调用的,因此考虑使用静态变量存储dataSource的key,在调用sql语句前设置静态变量的值,然后在这个方法中得到静态变量的值,返回。又考虑到多线程,同时可能会有很多请求,为避免线程之间相互干扰,考虑使用threadLocal。
先看存储dataSourceKey的容器类

package com.tongzuwang.datasource;

public class DBContextHolder {
	 
    /**
     * 线程threadlocal
     */
    private static ThreadLocal<String> contextHolder = new ThreadLocal<>();
 
    public static String master = "masterdataSource";
    public static String slave = "slavedataSource";
 
    public static String getDbType() {
        String db = contextHolder.get();
        if (db == null) {
            db = master;// 默认是读写库
        }
        return db;
    }
 
    /**
     * 
     * 设置本线程的dbtype
     * 
     * @param str
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static void setDbType(String str) {
        contextHolder.set(str);
    }
 
    /**
     * clearDBType
     * 
     * @Title: clearDBType
     * @Description: 清理连接类型
     */
    public static void clearDBType() {
        contextHolder.remove();
    }
}

第三部,在访问数据之前使用DBContextHolder的静态方法,设置数据源,默认是主库

DBContextHolder .setDbType(DBContextHolder .master);//设置数据源为主库

这是,我在CSDN的第一篇文章,水平比较低,大家见谅!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值