
SSM框架之多数据源配置
发布日期:2021-05-09 08:58:01
浏览次数:9
分类:博客文章
本文共 11310 字,大约阅读时间需要 37 分钟。
多数据源的应用场景:主要是数据库拆分后,怎样让多个数据库结合起来来达到业务需求。
SSM框架(Spring+SpringMVC+MyBatis(MyBatis-Plus))是目前最常用的,此次仍然是maven工程。
关于这个多数据源例子,我已经上传到我的github上,地址为:https://github.com/youcong1996/study_simple_demo.git
不过需要注意的是,分支为demo1,不是主分支,如图所示:
如果下面的示例,你们看不懂或者不能理解,可以git clone我的地址
在编程的世界里,简洁即完美。
如何实现多数据源?
一句话,三个类加xml配置即可达到这个目的。
一、编写三个类
AbstractDynamicDataSource.java
package com.blog.datasource;import java.util.Map;import javax.sql.DataSource;import org.apache.commons.collections.MapUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/** * 动态数据源父类 * @create ll * @update * @updateDate */public abstract class AbstractDynamicDataSourceextends AbstractRoutingDataSource implements ApplicationContextAware { /** 日志 */ protected Logger logger = LoggerFactory.getLogger(getClass()); /** 默认的数据源KEY */ protected static final String DEFAULT_DATASOURCE_KEY = "defaultDataSource"; /** 数据源KEY-VALUE键值对 */ public Map
DBContextHolder.java
package com.blog.datasource;import java.util.HashMap;import java.util.Map;public class DBContextHolder { /** 数据源的KEY */ public static final String DATASOURCE_KEY = "DATASOURCE_KEY"; /** 数据源的URL */ public static final String DATASOURCE_URL = "DATASOURCE_URL"; /** 数据源的驱动 */ public static final String DATASOURCE_DRIVER = "DATASOURCE_DRIVER"; /** 数据源的用户名 */ public static final String DATASOURCE_USERNAME = "DATASOURCE_USERNAME"; /** 数据源的密码 */ public static final String DATASOURCE_PASSWORD = "DATASOURCE_PASSWORD"; private static final ThreadLocal
DruidDynamicDataSource.java
package com.blog.datasource;import java.sql.SQLException;import java.util.List;import org.apache.commons.lang3.StringUtils;import com.alibaba.druid.filter.Filter;import com.alibaba.druid.pool.DruidDataSource;/** * Druid数据源 * @update * @updateDate */public class DruidDynamicDataSource extends AbstractDynamicDataSource{ private boolean testWhileIdle = true; private boolean testOnBorrow = false; private boolean testOnReturn = false; // 是否打开连接泄露自动检测 private boolean removeAbandoned = false; // 连接长时间没有使用,被认为发生泄露时长 private long removeAbandonedTimeoutMillis = 300 * 1000; // 发生泄露时是否需要输出 log,建议在开启连接泄露检测时开启,方便排错 private boolean logAbandoned = false; // 只要maxPoolPreparedStatementPerConnectionSize>0,poolPreparedStatements就会被自动设定为true,使用oracle时可以设定此值。 // private int maxPoolPreparedStatementPerConnectionSize = -1; // 配置监控统计拦截的filters private String filters; // 监控统计:"stat" 防SQL注入:"wall" 组合使用: "stat,wall" private List filterList; /* * 创建数据源 * @see com.cdelabcare.pubservice.datasource.IDynamicDataSource#createDataSource(java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ @Override public DruidDataSource createDataSource(String driverClassName, String url, String username, String password) { DruidDataSource parent = (DruidDataSource) super.getApplicationContext().getBean( DEFAULT_DATASOURCE_KEY); DruidDataSource ds = new DruidDataSource(); ds.setUrl(url); ds.setUsername(username); ds.setPassword(password); ds.setDriverClassName(driverClassName); ds.setInitialSize(parent.getInitialSize()); ds.setMinIdle(parent.getMinIdle()); ds.setMaxActive(parent.getMaxActive()); ds.setMaxWait(parent.getMaxWait()); ds.setTimeBetweenConnectErrorMillis(parent.getTimeBetweenConnectErrorMillis()); ds.setTimeBetweenEvictionRunsMillis(parent.getTimeBetweenEvictionRunsMillis()); ds.setMinEvictableIdleTimeMillis(parent.getMinEvictableIdleTimeMillis()); ds.setValidationQuery(parent.getValidationQuery()); ds.setTestWhileIdle(testWhileIdle); ds.setTestOnBorrow(testOnBorrow); ds.setTestOnReturn(testOnReturn); ds.setRemoveAbandoned(removeAbandoned); ds.setRemoveAbandonedTimeoutMillis(removeAbandonedTimeoutMillis); ds.setLogAbandoned(logAbandoned); // 只要maxPoolPreparedStatementPerConnectionSize>0,poolPreparedStatements就会被自动设定为true,参照druid的源码 ds.setMaxPoolPreparedStatementPerConnectionSize(parent .getMaxPoolPreparedStatementPerConnectionSize()); if (StringUtils.isNotBlank(filters)) try { ds.setFilters(filters); } catch (SQLException e) { throw new RuntimeException(e); } addFilterList(ds); return ds; } private void addFilterList(DruidDataSource ds) { if (filterList != null) { List targetList = ds.getProxyFilters(); for (Filter add : filterList) { boolean found = false; for (Filter target : targetList) { if (add.getClass().equals(target.getClass())) { found = true; break; } } if (!found) targetList.add(add); } } }}
二、修改配置文件
主要是修改spring-mybatis.xml
三、单元测试
import java.util.HashMap;import java.util.List;import java.util.Map;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.blog.datasource.DBContextHolder;import com.blog.entity.User;import com.blog.mapper.PostDao;import com.blog.service.UserService;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:spring/spring.xml")public class BlogTest { @Autowired private UserService ud; @Test public void testName() throws Exception { Mapmap = new HashMap (); map.put(DBContextHolder.DATASOURCE_KEY, "localhost"); map.put(DBContextHolder.DATASOURCE_DRIVER, "com.mysql.jdbc.Driver"); map.put(DBContextHolder.DATASOURCE_URL, "jdbc:mysql://127.0.0.1:3306/blog_test?useUnicode=true&characterEncoding=UTF-8"); map.put(DBContextHolder.DATASOURCE_USERNAME, "root"); map.put(DBContextHolder.DATASOURCE_PASSWORD, "1234"); DBContextHolder.setDBType(map); List list = ud.selectList(null); for (User user : list) { System.out.println(user); } }}
测试后,控制台如图:
小结:
其实配置多数据源有很多方式,有aop,也有配置多个bean的方式,当然了,只要能达到目的就是王道,当然了,我也强调一点,不是实现完就不管了,背后的为什么比只要实现就好更重要。
其实,有一点我想说的是,有些时候遇到难题,最好的方式是迎面而上解决这个问题,而不是逃避或者独自焦躁。同时直面问题,也是解决焦躁的最好方式。这个我已经深有体会了。
另外补充到,上传至github上的多数据源示例同时也是ssm框架的搭建。有哪位朋友不会搭建框架,可以参考我的这个。希望能对你们有什么帮助。
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2025年04月16日 22时38分01秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Spring Boot 2.4 配置文件将加载机制大变化
2019-03-06
MySQL错误日志(Error Log)
2019-03-06
oracle使用DBMS_RANDOM包生成随机数据
2019-03-06
C++高精度模板
2019-03-06
错题重错之WYT的刷子 单调队列
2019-03-06
联赛模拟测试23 D. 真相 思维题
2019-03-06
SSISDB2:SSIS工程的操作实例
2019-03-06
业务工作流平台设计(八)
2019-03-06
SpringBoot Web(SpringMVC)
2019-03-06
解决:angularjs radio默认选中失效问题
2019-03-06
windows环境下安装zookeeper(仅本地使用)
2019-03-06
Docker学习(十三)- docker rm 命令详解
2019-03-06
selnium远程机上传图片遇到的坑
2019-03-06
(转)在ASP.NET 中实现单点登录(利用Cache, 将用户信息保存在服务器缓存中)
2019-03-06
权限管理系统系列之序言
2019-03-06
微信小程序setData子元素
2019-03-06
数据泵使用NETWORK_LINK不落地导入数据
2019-03-06
刷LeetCode的简易姿势
2019-03-06
通过Attached Property给控件绑定Command(二)
2019-03-06