目前项目框架很简单,spring+spring jdbc。
客户想,
1,临时添加一个数据源,然后切换到此数据源,进行操作。
2,能保证每个数据源的表结构是统一的。
解决思路,spring jdbc用到的是jdbctemplate, jdbctemplate需要一个datasource。实现一个datasource,
把“判断连接哪个数据源”的条件存在 ThreadLocal 中,这样在自己的datasource里,就可以取出来使用。而不用
在service和dao中该代码了。
1,在controller层中切换数据源。根据id在一个固定数据源()中查找已经储存的数据源信息,把需要切换的数据源和当前登录用户绑定起来(这里自己任意实现)。
public String changeDBSource(){
if( !StringUtils.isBlank(id) ){
dbSource = databaseSourceService.findDBSourceById(id);
boolean b = false;
if(b){
//用户登录情况下,把dbSource与用户绑定。
}else{
//没有登录的情况下
ActionContext.getContext().getSession().put(DatabaseObserver.DBKEY, dbSource);
}
DatabaseObserver.put(dbSource);
}
if( StringUtils.isBlank(dbSource.getId())){
flag = "0";
}else{
flag = "1";
}
return "changeResult";
}
附上DatabaseObserver的代码,很简单
public class DatabaseObserver {
public static final String DBKEY = "dbkey";
private static ThreadLocal <DatabaseSource> dbSource = new ThreadLocal<DatabaseSource>();
public static void put (DatabaseSource dbs)
{
dbSource.set(dbs);
}
public static DatabaseSource get ()
{
return (DatabaseSource)dbSource.get();
}
}
2,与用户绑定后,用一个Filter过滤所有请求,把与用户绑定的数据源信息,通过DatabaseObserver写到ThreadLocal中。
public class ServerFilter extends HttpServlet implements Filter {
private static final long serialVersionUID = 6452049924844786456L;
private static FilterConfig filterConfig;
public void destroy() {
// TODO Auto-generated method stub
}
public void init(FilterConfig filterConfig) throws ServletException
{
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
boolean b = false;
//如果用户登录了,则把数据源信息与用户绑定
HttpServletRequest httpRequest = (HttpServletRequest)request;
if(b==true){
}
else{
//没有登录的情况下
DatabaseSource dbSource = (DatabaseSource)httpRequest.getSession().getAttribute(DatabaseObserver.DBKEY);
if(dbSource!=null){
DatabaseObserver.put(dbSource);
}
}
filterChain.doFilter(request, response);
}
}
3,最后在自己实现的datasource中,根据Threadlocal的数据源信息,返回的datasource。
public class DataSourceWithCache implements DataSource {
private static Map<String, DataSource> sources = new HashMap<String, DataSource>();
@Resource
private IDatabaseSourceService databaseSourceService ;
private DataSource getDataSource() {
DatabaseSource dbSource = DatabaseObserver.get();
if( dbSource == null ){
List<DatabaseSource> dbList = databaseSourceService.findBDSourcesByCond(dbSource, 0 , 1);
if(dbList.size()>0){
dbSource = dbList.get(0);
}
if( dbSource == null ){
return null;
}
}
DataSource source = sources.get(dbSource.getId());
if (source == null) {
source = createSource(dbSource);
sources.put(dbSource.getId(), source);
}
return source;
}
private DataSource createSource( DatabaseSource dbSource ) {
SingleConnectionDataSource source = new SingleConnectionDataSource();
source.setDriverClassName("com.mysql.jdbc.Driver");
source.setUrl(dbSource.getUrl());
source.setUsername(dbSource.getUsername());
source.setPassword(dbSource.getPassword());
source.setSuppressClose(true);
return source;
}
@Override
public Connection getConnection() throws SQLException {
return getDataSource().getConnection();
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
return getDataSource().getConnection(username, password);
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return getDataSource().getLogWriter();
}
@Override
public int getLoginTimeout() throws SQLException {
return getDataSource().getLoginTimeout();
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
getDataSource().setLogWriter(out);
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
getDataSource().setLoginTimeout(seconds);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return getDataSource().isWrapperFor(iface);
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return getDataSource().unwrap(iface);
}
public IDatabaseSourceService getDatabaseSourceService() {
return databaseSourceService;
}
public void setDatabaseSourceService(IDatabaseSourceService databaseSourceService) {
this.databaseSourceService = databaseSourceService;
}
}
分享到:
相关推荐
使用注解配置实现Spring动态数据源切换,实现原理 1、自定义动态数据源类DynamicDataSource: 实现spring类AbstractRoutingDataSource的方法determineCurrentLookupKey 2、自定义Spring AOP类DataSourceAspect 3、...
通过以上步骤,我们就实现了MyBatis与Spring配合下的动态数据源切换。这种机制有助于在多租户系统、读写分离或者高可用架构中灵活地管理数据库访问,提高了系统的可扩展性和灵活性。在实际应用中,还需要考虑数据源...
1. **Spring的AbstractRoutingDataSource**:这是Spring提供的核心类,用于实现动态数据源切换。这个抽象类维护了一个数据源路由决策表,可以根据特定的规则(如事务上下文、线程局部变量等)来决定使用哪个数据源。...
1. **Spring动态数据源**:Spring框架提供了动态数据源支持,允许我们在运行时根据需求切换或选择不同的数据源。这主要通过`AbstractRoutingDataSource`类实现,该类能够根据某种策略(如事务ID、用户名等)动态决定...
以下将详细介绍如何实现Spring的动态数据源切换以及相关知识点。 1. **数据源配置** - `jdbc.properties`: 这个文件通常包含了数据库连接的相关配置,如URL、用户名、密码、驱动类名等。Spring通过`Properties`类...
在Spring Boot应用中,数据源切换是一个常见的需求,特别是在分布式系统或者微服务架构中,可能需要连接多个数据库来实现不同的业务功能。本示例“spring boot数据源切换demo”将展示如何在Spring Boot中集成MyBatis...
【Spring 动态数据源切换】使用 `AbstractRoutingDataSource` 的详细实现在处理多数据库环境时,Spring 提供了一个强大的工具 `AbstractRoutingDataSource`,它允许我们根据特定条件动态地切换数据源。本文将深入...
"Spring动态切换多数据源Demo"是一个示例项目,它展示了如何在Spring中实现灵活的数据源切换。 首先,我们需要了解Spring中的数据源。在Spring中,数据源(DataSource)是Java中定义的javax.sql.DataSource接口的...
- AOP切面的Java类,实现了方法执行前后的拦截和数据源切换。 - 数据源相关的Java配置类,用于配置Spring的DataSource和MybatisPlus。 - Mapper接口和对应的XML文件,定义数据库操作。 - 业务逻辑层的Java类,其中的...
- **动态数据源切换逻辑**:核心逻辑是在AOP切面的Advice中实现。当一个需要切换数据源的方法被调用时,通过反射或其他机制获取该方法上标注的数据源信息,然后根据这些信息从数据源池中获取对应的数据源,并将其...
- 可以编写单元测试或集成测试,模拟不同场景下的数据源切换,确保功能正确无误。 - 使用日志记录数据源切换的过程,以便于调试和监控。 8. **最佳实践** - 避免在业务代码中直接切换数据源,最好通过服务层的...
在企业级应用开发中,Spring框架的广泛使用使得...通过这种方式,我们可以灵活地处理复杂的数据源切换场景,适应不同业务的需求。在实际项目中,还需要考虑线程安全、异常处理、测试等方面的问题,确保系统稳定运行。
然后,定义一个数据源切换的抽象类或接口,用于封装切换逻辑: ```java public interface DataSourceSwitcher { DataSource switchDataSource(DataSourceType type); } ``` 接着,实现这个接口,基于Spring的`...
在本文中,我们将深入探讨如何实现动态数据源切换,支持Spring声明式事务管理,并讨论多数据源回滚策略。以下是对这些知识点的详细说明: 1. **动态数据源切换**: - 通过AspectJ实现数据源的动态切换,可以设置在...
本文将深入探讨如何在SpringBoot项目中配置多数据源,并实现数据源的动态切换,帮助你理解和掌握这一核心技能。 首先,我们理解"多数据源"的概念。在SpringBoot应用中,多数据源意味着系统能够连接并操作多个不同的...
在实际项目中,我们还可以结合Spring的事务管理、AOP切面等特性,实现更加复杂的数据源切换策略,以满足各种业务需求。 总的来说,动态数据源是Spring框架中的一项强大功能,它允许我们在不修改代码的情况下,根据...
创建一个自定义的数据源切换注解,比如`@SwitchDataSource`,并在需要切换数据源的方法上使用。通过AspectJ的切面处理,我们可以在方法执行前后动态改变ThreadLocal中的数据源引用。 3. **Spring Cloud Config ...
综上所述,"spring+druid+AtomikosDataSource"的组合为开发者提供了一套强大的工具,用于实现多数据源切换和分布式事务控制。在实际项目中,通过合理的配置和编码,可以构建出高效、健壮的分布式系统。在`mult-table...
本主题将深入探讨如何利用SpringBoot结合Atomikos实现动态多数据源以及事务管理,并介绍两种切换数据源的方法。 首先,SpringBoot简化了传统Spring应用的初始化过程,它通过自动配置和starter包让开发者快速搭建...
3. **AOP实现动态数据源切换** 使用AOP(面向切面编程)注解,我们可以实现方法级别的数据源切换。创建一个`@Aspect`注解的类,定义一个环绕通知来切换数据源: ```java @Aspect @Component public class ...