SpringMVC框架中配置多数据源(测试库与正式库分离)

目的

为保护正式库数据相对安全,我们将系统中的数据库进行了分离。
开发者在windows环境开发时连接测试库,产品发布到Linux服务器上时连接正式库。

策略

鉴于开发环境与产品服务器存在系统差别,可以利用系统名称标识 os.name 来区分数据源。

步骤

  • 1、在jdbc.properties中添加以不同名称标识的路径参数,如:
driver=com.mysql.jdbc.Driver

#测试库
url-dev=jdbc:mysql://192.168.1.11:3306/db_xx?useUnicode=true&characterEncoding=utf8&autoReconnect=true
username-dev=user
password-dev=password

#正式库
url-pro=jdbc:mysql://192.168.1.201:3306/db_xx?useUnicode=true&characterEncoding=utf8&autoReconnect=true
username-pro=user
password-pro=password

#定义初始连接数  
initialSize=0
#定义最大连接数  
maxActive=20
#定义最大空闲  
maxIdle=20
#定义最小空闲  
minIdle=1
#定义最长等待时间  
maxWait=60000
  • 2、自定义AbstractRoutingDataSource,路径选择器
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {
    private static String dataSourceRef = "dataSource-dev"; // 数据源配置
    static {
        try {
            String os = System.getProperties().getProperty("os.name");
            if (os == null || os.length() == 0) {
                os = "win";
            }
            if (os.toLowerCase().startsWith("win")) {
                // 测试库
                dataSourceRef = "dataSource-dev";
            } else {
                // 正式库
                dataSourceRef = "dataSource-pro";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return dataSourceRef;
    }

}
  • 3、配置spring-mabatis.xml数据源部分
<!-- 本系统数据库配置 -->
    <bean id="dataSource-base" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${driver}" />
        <!-- 初始化连接大小 -->
        <property name="initialSize" value="${initialSize}"></property>
        <!-- 连接池最大数量 -->
        <property name="maxActive" value="${maxActive}"></property>
        <!-- 连接池最大空闲 -->
        <property name="maxIdle" value="${maxIdle}"></property>
        <!-- 连接池最小空闲 -->
        <property name="minIdle" value="${minIdle}"></property>
        <!-- 获取连接最大等待时间 -->
        <property name="maxWait" value="${maxWait}"></property>
    </bean>

    <!-- 测试库 -->
    <bean id="dataSource-dev" parent="dataSource-base">
        <property name="url" value="${url-dev}" />
        <property name="username" value="${username-dev}" />
        <property name="password" value="${password-dev}" />
    </bean>

    <!-- 正式库 -->
    <bean id="dataSource-pro"  parent="dataSource-base">
        <property name="url" value="${url-pro}" />
        <property name="username" value="${username-pro}" />
        <property name="password" value="${password-pro}" />
    </bean>

    <!-- 使用自定义的路径选择器 -->
    <bean id="dataSource" class="com.xxx.database.DynamicDataSource">
        <property name="defaultTargetDataSource" ref="dataSource-dev"/>
        <property name="targetDataSources">
            <map key-type="java.lang.String">
                <entry key="dataSource-dev" value-ref="dataSource-dev"></entry>
                <entry key="dataSource-pro" value-ref="dataSource-pro"></entry>
            </map>
        </property>
    </bean>

    <!-- spring和MyBatis整合 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:sqlMapConfig.xml"></property>
        <!-- 自动扫描mapping.xml文件 -->
        <property name="mapperLocations" value="classpath:com/xxx/mapper/*.xml"></property>
    </bean>

    <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.xxx.dao" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>

    <!-- (事务管理)transaction manager -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

小结

在当前业务特点下,我们通过增加AbstractRoutingDataSource实例实现了数据源的动态变更,巧妙的解决了多数据源的需求。

因为数据源在系统初始化时(static方法)就已经指定,因此不会出现切换数据源引发的异常。

我们看下org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource.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();

大概意思是决定当前连接的数据源(lookupKey),通过本方法返回需要使用的数据源ID即可动态修改连接配置。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值