spring-session-jdbc用数据库存储会话信息

x33g5p2x  于2022-09-23 转载在 Spring  
字(2.8k)|赞(0)|评价(0)|浏览(1368)

在 Redis 或数据库中存储会话详细信息通常是一个很好的方案。spring-session-jdbc 的默认实现也是使用主数据源来存储和检索会话相关表中的数据。但是当数据库有大量与会话相关的操作时,这可能是一个问题。

为避免这些情况,最好将与会话相关的模式移动到单独的数据库中。在这个例子中,我们将看到如何使用两个独立的数据库,一个用于存储应用程序数据,一个用于存储会话信息。

在这之前,我希望您先了解一下使用 Spring session 的JDBC ,以及如何实现 JDBC 会话存储的一些背景知识。

我们可以为与会话相关的自动配置提供数据源的最简单方法是定义一个带有 @SpringSessionDataSource 注释的 DataSource bean。起初,这似乎很容易,但事实并非如此。当您定义自己的 DataSource bean 时,它会弄乱默认的自动装配。要安全地提供第二个数据源,您需要遵循这些说明。

将会话存储在不同的数据库中

首先,为每个数据库创建两组属性。在我的例子中,我在演示中使用了两个独立的内存中 h2 数据库。

debug=true

# Properties for primary database
spring.datasource.url=jdbc:h2:mem:test
spring.datasource.username=root
spring.datasource.password=root
spring.h2.console.enabled=true

# Properties for session database
session.datasource.url=jdbc:h2:mem:sessions
session.datasource.username=sessions
session.datasource.password=sessions

然后使用 DataSourceProperties 属性手动创建这两个数据源。 spring.datasource 配置将用于创建主数据源。 session.datasource 属性将用于创建会话数据源。

@Configuration
public class DataSourceConfig {
    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource")
    @Qualifier("dataSource")
    public DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    public DataSource primaryDataSource(@Qualifier("dataSource") DataSourceProperties dataSourceProperties) {
        return dataSourceProperties
                .initializeDataSourceBuilder()
                .type(HikariDataSource.class)
                .build();
    }

    @Bean
    @ConfigurationProperties("session.datasource")
    @Qualifier("sessionDataSourceProperties")
    public DataSourceProperties sessionDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Qualifier("sessionDataSource")
    @SpringSessionDataSource
    public DataSource sessionDataSource(@Qualifier("sessionDataSourceProperties") DataSourceProperties sessionDataSourceProperties) {
        return sessionDataSourceProperties
                .initializeDataSourceBuilder()
                .type(HikariDataSource.class)
                .build();
    }
}

在上面的配置类中,请注意我如何将 sessionDataSource 标记为 @SpringSessionDataSource。此外,我已经确保数据源及其属性都可以通过使用 @Qualifier 的名称来区分。

初始化会话模式

如果您使用的是 Oracle 或 MySQL 之类的数据库,那么您已经完成了。在 sessionDataSource 指向的数据库中创建会话相关表 (SPRING_SESSION,SPRING_SESSION_ATTRIBUTES),一切顺利。但是如果你想使用这个演示中的嵌入式数据源,或者如果你将 spring.session.jdbc.initialize-schema 设置为 always,那么你就有问题了。

默认自动配置不知道要为 JdbcSessionDataSourceInitializer 自动装配哪个数据源。因此它最终可能会在主数据源中创建会话表。为避免这种情况,您需要提供自己的 JdbcSessionDataSourceInitializer bean,如下所示。

@Configuration
@EnableConfigurationProperties(JdbcSessionProperties.class)
public class JdbcSessionConfig {
    @Bean
    public JdbcSessionDataSourceInitializer
    jdbcSessionDataSourceInitializer(@Qualifier("sessionDataSource") DataSource sessionDataSource,
                                     ResourceLoader resourceLoader,
                                     JdbcSessionProperties properties) {
        return new JdbcSessionDataSourceInitializer(sessionDataSource, resourceLoader, properties);
    }
}

在上面的配置中,请注意我如何使用 @Qualifier 加载 sessionDataSource。另外,请注意,您需要 EnableConfigurationProperties 才能自动装配 JdbcSessionProperties

如果我们做对了这一切,你可以看到会话数据库有两个表,主数据库将被应用程序使用。

相关文章