在项目开发里面,多数据源是最普遍不过的,一个项目使用多个数据库是非常正常的,那么这篇就是基于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()); }
运行这个接口,我们会切换到第一个数据源进行操作,然后切换到第二个数据源进行操作,再切换到第一个数据源进行操作:
看下控制台输出(可以看到,切换自如):
好,多数据源的简单使用就到此吧。