标准 Spring 配置中的 @EnableJdbcHttpSession(无引导)
@EnableJdbcHttpSession in Standard Spring Config (no Boot)
我有一个 spring 应用程序和具有粘性会话的多节点服务器。我想将会话保留在数据库中,以免进行复制会话。
我尝试使用 @EnableJdbcHttpSession
实现 jdbc
会话存储,但我没有设法创建配置以使数据库中的会话正常工作。
我 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
但是当你启动应用程序时,会话没有存储在 table 中,我不知道我是否遗漏了配置中的任何内容,我发现的所有内容都应该设置这个但是它确实如此不工作,任何想法和帮助都欢迎我
主要问题是您覆盖了 AbstractHttpSessionApplicationInitializer
的 onStartup
方法,破坏了 AbstractHttpSessionApplicationInitializer
的整个目的,即注册 AbstractHttpSessionApplicationInitializer
所需的过滤器=48=] 会话完成它的工作。
我建议使用多个 WebApplicationInitializer
以便您可以利用默认设置而不是重新发明轮子。在您的情况下,这意味着 3 WebApplicationInitializer
。
- Bootstrap 您的应用程序和 servlet
- 配置安全性
- 配置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
以确保它们以正确的顺序执行。
我有一个 spring 应用程序和具有粘性会话的多节点服务器。我想将会话保留在数据库中,以免进行复制会话。
我尝试使用 @EnableJdbcHttpSession
实现 jdbc
会话存储,但我没有设法创建配置以使数据库中的会话正常工作。
我 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
但是当你启动应用程序时,会话没有存储在 table 中,我不知道我是否遗漏了配置中的任何内容,我发现的所有内容都应该设置这个但是它确实如此不工作,任何想法和帮助都欢迎我
主要问题是您覆盖了 AbstractHttpSessionApplicationInitializer
的 onStartup
方法,破坏了 AbstractHttpSessionApplicationInitializer
的整个目的,即注册 AbstractHttpSessionApplicationInitializer
所需的过滤器=48=] 会话完成它的工作。
我建议使用多个 WebApplicationInitializer
以便您可以利用默认设置而不是重新发明轮子。在您的情况下,这意味着 3 WebApplicationInitializer
。
- Bootstrap 您的应用程序和 servlet
- 配置安全性
- 配置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
.
@Order(2)
public SecurityInitializer extends AbstractSecurityWebApplicationInitializer() {}
这 class 就是您所需要的,因为它将从预先加载的根上下文中检测配置。
最后你想要 Spring Session 东西并为此创建一个 class 扩展 AbstractHttpSessionApplicationInitializer
.
@Order(3)
public SpringSessionInitializer extends AbstractHttpSessionApplicationInitializer {}
再次满足您的所有需求,因为它将检测先前创建的配置中的过滤器。您可能想在每个上放置一个 @Order
以确保它们以正确的顺序执行。