SSM 最简单的实现操作 多数据源&动态切换

在项目开发里面,多数据源是最普遍不过的,一个项目使用多个数据库是非常正常的,那么这篇就是基于SSM框架去轻松实现使用多数据源的实战场景。

基于SSM框架(还不了解SSM的的可以参考:https://blog.csdn.net/qq_35387940/article/details/97911104

开始,

 首先准备2个不同的数据源(多个也行),在jdbc.properties:


#数据源 1
first_driverClass =com.mysql.jdbc.Driver
first_jdbcUrl=jdbc:mysql://localhost:3306/game_message?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
first_username=root
first_password=root

#数据源 2
second_driverClass=com.mysql.jdbc.Driver
second_jdbcUrl=jdbc:mysql://localhost:3306/web_slave?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
second_username=root
second_password=root


#定义初始连接数
initialSize=0
#定义最大连接数
maxActive=20
#定义最大空闲
maxIdle=20
#定义最小空闲
minIdle=1
#定义最长等待时间
maxWait=60000

然后在applicationContext.xml上面做修改,将原来只有一个数据源的配置改成多个(请看配置里的注释):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:beans="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-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/mvc
         http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd ">

    <!-- ①:对com.springmvc包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 -->
    <context:component-scan base-package="com.springmvc"/>

    <mvc:annotation-driven />
    <!-- 静态资源访问 -->
    <!--如果webapp下你新建了文件夹,想访问里面的静态资源,那么就要在这配置一下-->
    <mvc:resources location="/images/" mapping="/images/**"/>
    <mvc:resources location="/css/" mapping="/css/**"/>
    <mvc:resources location="/styles/" mapping="/styles/**"/>
    <mvc:resources location="/js/" mapping="/js/**"/>

    <!-- 开启mvc注解 -->
    <mvc:annotation-driven >
        <!-- 处理responseBody 里面日期类型 -->
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                        <property name="dateFormat">
                            <bean class="java.text.SimpleDateFormat">
                                <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss" />
                            </bean>
                        </property>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>



    <!-- Configures the @Controller programming model
    <mvc:annotation-driven />-->
    <!-- ②:启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="mappingJacksonHttpMessageConverter"/>
            </list>
        </property>
    </bean>
    <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>application/json;charset=UTF-8</value>
            </list>
        </property>
    </bean>


    <!-- 配置视图解析器,把控制器的逻辑视频映射为真正的视图 -->
    <!-- /WEB-INF/jsp/start.jsp -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>


    <!-- <context:property-placeholder location="classpath:db.properties"/> -->
    
    
    <!--数据库配置 -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath*:jdbc.properties</value>
            </list>
        </property>
        <property name="ignoreUnresolvablePlaceholders" value="true" />
    </bean>
    
    <!-- 配置第一个数据源 -->
    <bean id="firstSource" class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close">
        <property name="driverClassName" value="${first_driverClass}"/>
        <property name="url" value="${first_jdbcUrl}"/>
        <property name="username" value="${first_username}"/>
        <property name="password" value="${first_password}"/>
        <!-- 初始化连接大小 -->
        <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="secondSource" class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close">
        <property name="driverClassName" value="${second_driverClass}"/>
        <property name="url" value="${second_jdbcUrl}"/>
        <property name="username" value="${second_username}"/>
        <property name="password" value="${second_password}"/>
        <!-- 初始化连接大小 -->
        <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" class="com.springmvc.dynamicsource.DynamicDataSource">
        <property name="targetDataSources">
            <map key-type="java.lang.String">
                <!-- 指定lookupKey和与之对应的数据源,这里的key可以自行定义,要切换数据库的时候以key为标识,不要写错 -->
                <entry key="firstSource" value-ref="firstSource"></entry>
                <entry key="secondSource" value-ref="secondSource"></entry>
            </map>
        </property>
        <!-- 这里可以指定默认的数据源 -->
        <property name="defaultTargetDataSource" ref="firstSource" />
    </bean>


    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 配置会话工厂SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:mybatis.xml" />
        <property name="mapperLocations" value="classpath:sqlmap/*Mapper.xml"/>
        <property name="typeAliasesPackage" value="com.springmvc.entity" />
    </bean>
    <!-- 在spring容器中配置mapper的扫描器产生的动态代理对象在spring的容器中自动注册,bean的id就是mapper类名(首字母小写)-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 指定扫描包的路径,就是mapper接口的路径,多个包中间以 半角逗号隔开   -->
        <property name="basePackage" value="com.springmvc.dao"/>
        <!-- 配置sqlSessionFactoryBeanName -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>


    <!-- 拦截器 -->
    <mvc:interceptors>
        <!-- 国际化操作拦截器 如果采用基于(请求/Session/Cookie)则必需配置 -->
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
    </mvc:interceptors>
    <!-- 定义无Controller的path<->view直接映射 -->
    <!-- <mvc:view-controller path="/" view-name="redirect:/" /> -->



</beans>

然后是定义动态数据源,DynamicDataSource.java:

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


/**
 * @Author : JCccc
 * @CreateTime : 2019/8/15
 * @Description :
 **/
public class DynamicDataSource extends AbstractRoutingDataSource{

//定义动态数据源,集成spring提供的AbstractRoutingDataSource,实现determineCurrentLookupKey

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceHolder.getDataSource();
    }



}

接着是动态切换数据源方法类,DynamicDataSourceHolder.java:

/**
 * @Author : JCccc
 * @CreateTime : 2019/8/15
 * @Description :
 **/
public class DynamicDataSourceHolder
{
    private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal();

    public static String getDataSource()
    {
        return (String)THREAD_DATA_SOURCE.get();
    }

    public static void setDataSource(String dataSource)
    {
        THREAD_DATA_SOURCE.set(dataSource);
    }

    public static void clearDataSource()
    {
        THREAD_DATA_SOURCE.remove();
    }
}

到这,多数据源已经实现了,我们在切换数据源,使用的时候只需要用以下这行代码进行切换:

DynamicDataSourceHolder.setDataSource("XXXX"); //值为配置文件里面数据源设置的加载key

最后测试下,写一个接口简单测试下:


    @Autowired
    MessageboardService messageboardServiceImpl;
    @Autowired
    JdbcConfigService jdbcConfigServiceImpl;

    @RequestMapping(value = "/testDbSource", produces = "application/json; charset=utf-8")
    public void testDbSource() {

        DynamicDataSourceHolder.setDataSource("firstSource"); //切换到数据源1
        Messageboard  message = messageboardServiceImpl.selectByPrimaryKey(5);
        System.out.println(message.toString());
        DynamicDataSourceHolder.setDataSource("secondSource"); //切换到数据源2
        JdbcConfig jdbcConfig = jdbcConfigServiceImpl.selectByGameId("1234");
        System.out.println(jdbcConfig.toString());
        DynamicDataSourceHolder.setDataSource("firstSource"); //切换到数据源1
        Messageboard  messageExtra = messageboardServiceImpl.selectByPrimaryKey(4);
        System.out.println(messageExtra.toString());
    }

运行这个接口,我们会切换到第一个数据源进行操作,然后切换到第二个数据源进行操作,再切换到第一个数据源进行操作:

看下控制台输出(可以看到,切换自如):

 好,多数据源的简单使用就到此吧。

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小目标青年

对你有帮助的话,谢谢你的打赏。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值