#spring #session #events #hazelcast
Вопрос:
Я не получаю события закрытия сеанса или истечения срока действия при использовании встроенного репозитория сеансов Hazelcast в приложении Spring boot. Я действительно получаю события создания сеанса. У меня очень короткий тайм-аут для сеансов (30 секунд). Я проверил, что срок действия сеанса истекает через 30 секунд, получив «несанкционированный» ответ с сервера. Как вы получаете события истечения/уничтожения сеанса?
Это моя конфигурация сеанса:
@Configuration
@EnableHazelcastHttpSession(maxInactiveIntervalInSeconds = 30)
public class SessionConfiguration{
@Bean
@SpringSessionHazelcastInstance
public HazelcastInstance hazelcastInstance() {
Config config = new Config();
config.setClusterName("spring-session-cluster");
// Add this attribute to be able to query sessions by their PRINCIPAL_NAME_ATTRIBUTE's
AttributeConfig attributeConfig = new AttributeConfig()
.setName(Hazelcast4IndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE)
.setExtractorClassName(Hazelcast4PrincipalNameExtractor.class.getName());
// Configure the sessions map
config.getMapConfig(Hazelcast4IndexedSessionRepository.DEFAULT_SESSION_MAP_NAME)
.addAttributeConfig(attributeConfig).addIndexConfig(
new IndexConfig(IndexType.HASH, Hazelcast4IndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE));
// Use use custom serializer to de/serialize sessions faster. This is optional.
SerializerConfig serializerConfig = new SerializerConfig();
serializerConfig.setImplementation(new HazelcastSessionSerializer()).setTypeClass(MapSession.class);
config.getSerializationConfig().addSerializerConfig(serializerConfig);
return Hazelcast.newHazelcastInstance(config);
}
@Bean
public SessionRepositoryCustomizer<Hazelcast4IndexedSessionRepository> customize() {
return (sessionRepository) -> {
sessionRepository.setFlushMode(FlushMode.IMMEDIATE);
sessionRepository.setSaveMode(SaveMode.ALWAYS);
sessionRepository.setSessionMapName(Hazelcast4IndexedSessionRepository.DEFAULT_SESSION_MAP_NAME);
sessionRepository.setDefaultMaxInactiveInterval(30); //this is extra; tried with and without
};
}
}
И это мой слушатель:
@Component
public class SessionListener {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SessionListener.class);
@EventListener
public void sessionCreated(SessionCreatedEvent event) {
log.info("SESSION:CREATE:ID=" event.getSessionId()); //only this gets called but none of the others
}
@EventListener
public void sessionDeleted(SessionDeletedEvent event) {
log.info("SESSION:DELETE:ID=" event.getSessionId());
}
@EventListener
public void sessionDestroyed(SessionDestroyedEvent event) {
log.info("SESSION:DESTROY:ID=" event.getId());
}
@EventListener
public void sessionExpired(SessionExpiredEvent event) {
log.info("SESSION:EXPIRE:ID=" event.getSessionId());
}
}
Ответ №1:
Частичный ответ (я точно не знаю, почему это работает):
Если вы добавите прослушиватель карты сеанса в HazelcastInstance (в компоненте создания), вы внезапно начнете получать события Sessionexpired.
Поэтому замените строки:
config.getMapConfig(Hazelcast4IndexedSessionRepository.DEFAULT_SESSION_MAP_NAME)
.addAttributeConfig(attributeConfig).addIndexConfig(
new IndexConfig(IndexType.HASH, Hazelcast4IndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE));
с (установите максимальное количество секунд простоя в конфигурации карты сеанса):
config.getMapConfig(Hazelcast4IndexedSessionRepository.DEFAULT_SESSION_MAP_NAME)
.addAttributeConfig(attributeConfig).addIndexConfig(
new IndexConfig(IndexType.HASH, Hazelcast4IndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE))
.setMaxIdleSeconds(tout);
и
return Hazelcast.newHazelcastInstance(config);
с помощью (добавить прослушиватель записи сеанса на карту сеанса)
HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);
IMap<Object, Object> map = instance.getMap( Hazelcast4IndexedSessionRepository.DEFAULT_SESSION_MAP_NAME );
map.addEntryListener( new HazelcastSessionEntryListener(), true );
return instance;
где HazelcastSessionEntryListener может быть определен следующим образом:
@Component
public class HazelcastSessionEntryListener implements EntryListener<Object, Object>
{
public HazelcastSessionEntryListener(){}
@Override
public void entryAdded(EntryEvent<Object, Object> event){}
@Override
public void entryUpdated(EntryEvent<Object, Object> event){}
@Override
public void entryRemoved(EntryEvent<Object, Object> event){}
@Override
public void entryEvicted(EntryEvent<Object, Object> event){}
@Override
public void entryExpired(EntryEvent<Object, Object> event){}
@Override
public void mapCleared(MapEvent event){}
@Override
public void mapEvicted(MapEvent event){}
}
Забавно, что HazelcastSessionEntryListener в моем случае-это просто пустая реализация (она ничего не делает). Похоже на поведение с ошибками (но я не эксперт по весне).