最近在开发项目中(ORM层用的是mybatis),需要连接多个数据库,这时候就涉及到多数据源使用了。为了优雅的解决此问题,我们可以使用装饰者模式并修改了mybatis的实现源码来优雅的解决此问题 由于代码量有点多,文章篇幅有限,就不在此详细的搬出,具体的代码已放到git 飞机票如下https://github.com/skybluehhx/mulitDataSource.git(现已更新支持注解的方式)。
首先回顾下数据也就是DataSource这个接口的作用
public interface DataSource extends CommonDataSource, Wrapper {
/**
* 尝试使用该数据源去获取连接
*/
Connection getConnection() throws SQLException;
/**
*
*/
Connection getConnection(String username, String password)
throws SQLException;
}
假设现在我们有两个数据源A和B,我们可以使用自写一个数据源实现C,根据我们的需求从A或B中去获取具体实现,伪代码如下
/**
* @author jianglinzou
* @date 2019/7/4 下午7:52
*/
public class C implements DataSource {
private DataSource A;
private DataSource B;
@Override
public Connection getConnection() throws SQLException {
return null;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
if (需要获取A数据源的连接) {
return A.getConnection(username, password);
} else if (需要获取B数据源的连接) {
return B.getConnection(username, password);
}
return null;
}
//其他方法略
}
首先,根据我们的请求依据什么去获取具体的数据源连接,这个可以在request中确定,当发起请求时,我们需要自己去设置请求的数据源,
第二,由于request位于controller层,如何无缝的从request中获取需要请求的数据源名称呢,答案是通过threadlocal类,当请求来临时,我们从request中获取需要的数据名称,并放入threadlocal中,由于执行该方法与放入threadlocal的线程为同一线程,获取时我们直接从threadlocal中获取中即可。核心代码如下
//拦截器,从request中获取需要的数据源名称
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
String dataSource = request.getParameter(DATA_SOURCE_PARAM_NAME);
if (Strings.isBlank(dataSource)) {
dataSource = request.getHeader(DATA_SOURCE_PARAM_NAME);
}
//该方法将需要的dataSource放入threadlocal中国
MulitDataSourceSupport.putDataSourceName(request, dataSource);
return true;
}
获取连接
public Connection getConnection(String username, String password) throws
SQLException {
DataSource dataSource = getDataSource();
return dataSource.getConnection(username, password);
}
protected DataSource getDataSource() {
String dataSourceName = MulitDataSourceSupport.getDataSourceName();
logger.info("will to get dataSourceName:{}", dataSourceName);
DataSource dataSource = getDataSourceFromApplication(dataSourceName);
return dataSource;
}
另一种方式是依托于注解,这里就不演示了,大家可以https://github.com/skybluehhx/mulitDataSource.git上获取完整代码
上述就是多数据源配置的核心代码,巧妙的运用了装饰者模式来解决实际问题,上述只是简单的讲解,大家获取完整的代码。根据readme提示运行实例即可。