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

时间:2018-04-18 12:26:56

标签: java spring spring-session

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

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

我在spring-session-jdbc中有pom.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

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

1 个答案:

答案 0 :(得分:0)

主要问题是你已经覆盖了onStartup的{​​{1}}方法,你打破了AbstractHttpSessionApplicationInitializer的整个目的,即将Spring Session所需的过滤器注册到做它的工作。

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

  1. 引导您的应用程序和servlet
  2. 配置安全性
  3. 配置Spring Session
  4. 要配置您的应用程序,我建议扩展WebApplicationInitializer,这基本上就是您现在手动执行的操作。

    AbstractAnnotationConfigDispatcherServletInitializer

    现在您已经加载了所有配置,您需要启用Spring Security,以创建一个扩展@Order(1) public MainApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { protected Class<?>[] getRootConfigClasses() { return new Class[] { AppConfig.class, WebSecurity.class}; } protected Class<?>[] getServletConfigClasses() { return new Class[] { WebMvc.class }; } } 的类。

    AbstractSecurityWebApplicationInitializer

    这个类就是您所需要的,因为它将从之前加载的根上下文中检测配置。

    最后你需要Spring Session的东西,为此创建一个扩展@Order(2) public SecurityInitializer extends AbstractSecurityWebApplicationInitializer() {} 的类。

    AbstractHttpSessionApplicationInitializer

    再次需要,因为它将检测先前创建的配置中的过滤器。您可能希望在每个上放置一个@Order(3) public SpringSessionInitializer extends AbstractHttpSessionApplicationInitializer {} ,以确保它们以正确的顺序执行。