如何将 Spring AbstractRoutingDataSource 与动态数据源一起使用?

2024-03-06

我正在使用 Spring、Spring Data JPA、Spring Security、Primefaces 的项目......

我正在关注本教程 http://spring.io/blog/2007/01/23/dynamic-datasource-routing/关于 spring 的动态数据源路由。

在本教程中,您只能实现预定义数据源之间的动态数据源切换。

这是我的代码片段:

springContext-jpa.xml

<bean id="dsCgWeb1" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName.Cargest_web}"></property>
    <property name="url" value="${jdbc.url.Cargest_web}"></property>
    <property name="username" value="${jdbc.username.Cargest_web}"></property>
    <property name="password" value="${jdbc.password.Cargest_web}"></property>
</bean>

<bean id="dsCgWeb2" class="org.apache.commons.dbcp.BasicDataSource">
    // same properties, different values ..
</bean>

<!--  Generic Datasource [Default : dsCargestWeb1]  -->
<bean id="dsCgWeb" class="com.cargest.custom.CargestRoutingDataSource">
    <property name="targetDataSources">
        <map>
            <entry key="1" value-ref="dsCgWeb1" />
            <entry key="2" value-ref="dsCgWeb2" />
        </map>
    </property>
    <property name="defaultTargetDataSource" ref="dsCgWeb1" />
</bean>

我想做的是使目标数据源地图动态也与其元素相同。

换句话说,我想获取某个数据库表,使用该表中存储的属性来创建我的数据源,然后将它们放入像这样的地图中目标数据源.

有没有办法做到这一点 ?


里面什么都没有AbstractRoutingDataSource强制你使用静态地图DataSourceS。由你来构建一个 bean 来实现Map<Object, Object>,其中 key 是您用来选择的DataSource,价值是DataSource或(默认情况下)引用 JNDI 定义的数据源的字符串。您甚至可以动态修改它,因为当地图存储在内存中时,AbstractRoutingDataSource不进行缓存。

我没有完整的示例代码。但这是我能想象到的。在 Web 应用程序中,每个客户端都有一个数据库,所有数据库都具有相同的结构 - 好吧,这将是一个奇怪的设计,假设这只是为了示例。在登录时,应用程序为客户端创建数据源并将其存储在由 sessionId 索引的映射中 - 该映射是根上下文中名为的 beandataSources

@Autowired
@Qualifier("dataSources");
Map<String, DataSource> sources;

// I assume url, user and password have been found from connected user
// I use DriverManagerDataSource for the example because it is simple to setup
DataSource dataSource = new DriverManagerDataSource(url, user, password);
sources.put(request.getSession.getId(), dataSource);

您还需要一个会话监听器来清理dataSources in its destroy method

@Autowired
@Qualifier("dataSources");
Map<String, DataSource> sources;

public void sessionDestroyed(HttpSessionEvent se)  {
    // eventually cleanup the DataSource if appropriate (nothing to do for DriverManagerDataSource ...)
    sources.remove(se.getSession.getId());
}

路由数据源可能是这样的:

public class SessionRoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        HttpServletRequest request = ((ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes()).getRequest();
        return request.getSession().getId();
    }

    @Autowired
    @Qualifier("dataSources")
    public void setDataSources(Map<String, DataSource> dataSources) {
        setTargetDataSources(dataSources);
}

我没有测试任何东西,因为设置不同的数据库需要很多工作,但我认为应该没问题。在现实世界中,每个会话不会有不同的数据源,而是每个用户都有一个数据源,每个用户有一个会话计数,但正如我所说,这是一个过于简化的示例。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 Spring AbstractRoutingDataSource 与动态数据源一起使用? 的相关文章

随机推荐