标准 Spring 配置中的 @EnableJdbcHttpSession(无引导)

@EnableJdbcHttpSession in Standard Spring Config (no Boot)

我有一个 spring 应用程序和具有粘性会话的多节点服务器。我想将会话保留在数据库中,以免进行复制会话。

我尝试使用 @EnableJdbcHttpSession 实现 jdbc 会话存储,但我没有设法创建配置以使数据库中的会话正常工作。

spring-session-jdbcpom.xml:

    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-jdbc</artifactId>
        <version>2.0.2.RELEASE</version>
        <type>pom</type>
    </dependency>

还有:

@Configuration
@EnableTransactionManagement
@EnableJdbcHttpSession
public class AppConfig{

    @Autowired
    private AppEnvironment env;

    @Bean(name = "dataSource")
    public DataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getDriverClassName());
        dataSource.setUrl(env.getDatabaseUrl());
        dataSource.setUsername(env.getDatabaseUserName());
        dataSource.setPassword(env.getDatabasePassword());
        dataSource.setValidationQuery(env.getDatabaseValidationQuery());
        dataSource.setTestOnBorrow(env.isTomcatTestOnBorrow());
        return dataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

        HibernateJpaVendorAdapter jpaAdapter = new HibernateJpaVendorAdapter();
        jpaAdapter.setShowSql(Boolean.valueOf(env.isJpaShowSql()));
        jpaAdapter.setDatabase(Database.SQL_SERVER);

        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setPersistenceProvider(new HibernatePersistenceProvider());
        em.setDataSource(dataSource());
        em.setPackagesToScan(new String[] { "com.humanbizz.web.entities" });
        em.setPersistenceUnitName("persistenceUnit");
        em.setJpaVendorAdapter(jpaAdapter);
        em.setJpaProperties(additionalProperties());

        return em;
    }

    Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", env.getHibernateDialect());
        properties.setProperty("hibernate.default_catalog", env.getDefaultCatalog());
        properties.setProperty("hibernate.hbm2ddl.auto", env.getHbm2ddlAuto());

        properties.setProperty("hibernate.id.new_generator_mappings", String.valueOf(env.isIdNewGeneratorMappings()));
        properties.setProperty("hibernate.default_schema", env.getDefaultSchema());
        properties.setProperty("hibernate.connection.useUnicode", String.valueOf(env.isConnectionUseUnicode()));
        properties.setProperty("hibernate.connection.charSet", env.getConnectionCharSet());
        return properties;
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource); 
    }

}

我的 HttpSessionApplicationInitializer:

public class HttpSessionApplicationInitializer extends AbstractHttpSessionApplicationInitializer{

    public HttpSessionApplicationInitializer() {
        super(AppConfig.class); 
    }

    @Override
    public void onStartup(ServletContext container) {

      AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
      rootContext.register(WebSecurity.class, Datasource.class);

      container.addListener(new ContextLoaderListener(rootContext));

      AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
      dispatcherContext.register(WebMvc.class);

      ServletRegistration.Dynamic dispatcher =  container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
      dispatcher.setLoadOnStartup(1);
      dispatcher.addMapping("/");

      container.addFilter("securityFilter",  new DelegatingFilterProxy("springSecurityFilterChain"))
      .addMappingForUrlPatterns(null, false, "/*");

    }

}

我在数据库中有一个生成的方案,就像这里 https://github.com/spring-projects/spring-session/blob/master/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sqlserver.sql

但是当你启动应用程序时,会话没有存储在 table 中,我不知道我是否遗漏了配置中的任何内容,我发现的所有内容都应该设置这个但是它确实如此不工作,任何想法和帮助都欢迎我

主要问题是您覆盖了 AbstractHttpSessionApplicationInitializeronStartup 方法,破坏了 AbstractHttpSessionApplicationInitializer 的整个目的,即注册 AbstractHttpSessionApplicationInitializer 所需的过滤器=48=] 会话完成它的工作。

我建议使用多个 WebApplicationInitializer 以便您可以利用默认设置而不是重新发明轮子。在您的情况下,这意味着 3 WebApplicationInitializer

  1. Bootstrap 您的应用程序和 servlet
  2. 配置安全性
  3. 配置Spring会话

要配置您的应用程序,我建议扩展 AbstractAnnotationConfigDispatcherServletInitializer,它基本上可以完成您现在手动完成的所有工作。

@Order(1)
public MainApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { AppConfig.class, WebSecurity.class};
    }

    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebMvc.class };
    }        
}

现在您已经加载了所有配置,您需要启用 Spring 安全性,创建一个扩展 AbstractSecurityWebApplicationInitializer.

的 class
@Order(2)
public SecurityInitializer extends AbstractSecurityWebApplicationInitializer() {}

这 class 就是您所需要的,因为它将从预先加载的根上下文中检测配置。

最后你想要 Spring Session 东西并为此创建一个 class 扩展 AbstractHttpSessionApplicationInitializer.

@Order(3)
public SpringSessionInitializer extends AbstractHttpSessionApplicationInitializer {}

再次满足您的所有需求,因为它将检测先前创建的配置中的过滤器。您可能想在每个上放置一个 @Order 以确保它们以正确的顺序执行。