作者:wuqing0625 | 来源:互联网 | 2024-11-04 12:13
在近期的项目开发过程中,ORM层采用了MyBatis,并且需要连接多个数据库,这带来了多数据源配置的挑战。为了解决这一问题,我们可以通过巧妙运用注解来实现优雅的数据源切换,确保系统的灵活性和可维护性。这种方法不仅简化了配置,还提高了代码的可读性和扩展性。
最近在开发项目中(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;@Overridepublic Connection getConnection() throws SQLException {return null;}@Overridepublic 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中获取需要的数据源名称@Overridepublic 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提示运行实例即可。