Vaadin 14 addDestroyListener для сеанса, отличного от int SessionDestroyListener
есть ли другой способ добавить действия для уничтожения определенного сеанса иначе, чем путем реализации SessionDestroyListener. Я хочу запустить его в других местах кода. Например, я хочу удалить некоторые данные из статического списка, которые назначены для сеанса, который будет уничтожен, но оставил другие элементы в этом списке, которые назначены для все еще живых сеансов. Я попытался добавить что-то вроде этого:
ui.getSession().getService().addSessionDestroyListener( evt -> {
list.remove(this);
});
Но затем этот слушатель запускается, как и ожидалось, когда какой-то сеанс уничтожается, но затем он запускается также для все еще живых сеансов. Таким образом, после уничтожения одного сеанса элементы для всех сеансов удаляются. При отладке я обнаружил, что у каждого сеанса есть одна и та же служба.
Я использую Ваадин 14.8.14.
Я хочу запустить прослушиватель уничтожения только для сеанса, в который он был добавлен.
2 ответа
Вы можете выполнять действия для каждого сеанса с помощьюVaadinService::addSessionDestroyListener
путем добавления фактического прослушивателя только один раз (например, вVaadinServiceInitListener
и сохранение фактического действия в качестве атрибута в каждом сеансе.
Для конкретного примера, который вы показываете, вы можете сохранить элемент списка для удаления в каждом сеансе:
someSession.setAttribute("item-to-remove", someItem);
И тогда прослушиватель singleton может сделать что-то вроде этого:
Object itemToRemove = event.getSession().getAttribute("item-to-remove");
list.remove(itemToRemove);
Для более сложных случаев вы также можете хранить в сеансе обратный вызов, а не только данные.
Следует отметить одну несвязанную вещь: несколько событий уничтожения сеанса могут запускаться одновременно, что означает, что вам необходимо защитить свой список от одновременной модификации, например, с помощьюCopyOnWriteArrayList
или используяCollections::synchronizedList
.
Я заставил его работать с сопоставлением VaadinSession с SpringVaadinSession, а затем с помощью addDestroyLsitener:
VaadinSession session = SpringVaadinSession.getCurrent();
if(session instanceof SpringVaadinSession) {
((SpringVaadinSession) session).addDestroyListener(evt -> {
someFunctionThatIsfiredWhenSessionIsDestoryed();
});
}
Я создал эту проблему с максимально простым кодом, но я хочу использовать его для более сложных действий, например, для выполнения более длинных функций, чем одна строка кода.