События UI
ApplicationEvent
из Spring можно использовать для реагирования на события в различных частях приложения.
Чтобы отослать события компонентам UI, включая открытые экраны, необходимо использовать бин UiEventPublisher
фреймворка.
Бин UiEventPublisher
предоставляет следующие методы:
-
publishEventForCurrentUI()
- публикует событие только для текущей активной вкладки браузера, из которой было отправлено событие. -
publishEvent()
- публикует событие для всех вкладок браузера в текущей сессии. -
publishEventForUsers()
- публикует событие для всех вкладок браузера для всех сессий пользователей, указанных в коллекцииusernames
, которая передается в качестве второго параметра. Если коллекцияusernames
равнаnull
, событие будет опубликовано для всех пользователей.
Для правильного обновления UI класс, реализующий AppShellConfigurator
, должен содержать аннотацию @Push
. Обычно это основной класс приложения Spring Boot:
@Push
@SpringBootApplication
public class OnboardingApplication implements AppShellConfigurator {
Пример использования
Рассмотрим следующую задачу: пользователи должны завершить процесс онбординга, следуя определенным шагам. Каждый шаг представлен экземпляром сущности, и есть экран, который показывает информацию о завершенных шагах. Кроме того, пользователям нужно напоминание о количестве незавершенных шагов, которое обновляет свое значение каждый раз, когда состояние шагов изменяется. Например, таким напоминанием может быть значок в элементе меню.
Экземпляры сущностей, представляющие шаги, могут обновляться на экранах деталей сущностей или в бизнес-логике приложения. Значок элемента меню должен обновляться каждый раз, когда сущность, связанная с текущим пользователем, изменяется.
Задачу можно решить следующим образом:
-
Создайте класс события:
import org.springframework.context.ApplicationEvent; public class OnboardingStatusChangedEvent extends ApplicationEvent { public OnboardingStatusChangedEvent(Object source) { super(source); } }
-
Создайте слушатель события в экране, который должен быть уведомлен. В приведенном ниже примере это главный экран:
@Subscribe public void onInit(final InitEvent event) { updateOnboardingStatus(); (1) } @EventListener private void onBoardingStatusChanged(OnboardingStatusChangedEvent event) { (2) updateOnboardingStatus(); } private void updateOnboardingStatus() { long number = getUncompletedStepsNumber(); (3) Span badge = null; (4) if (number > 0) { badge = new Span("" + number); badge.getElement().getThemeList().add("badge warning"); } ListMenu.MenuItem menuItem = menu.getMenuItem("MyOnboardingView"); // Can be 'null' if menu item isn't permitted by security if (menuItem != null) { menuItem.setSuffixComponent(badge); } }
1 Обновление статуса онбординга в первый раз, когда пользователь открывает главный экран. 2 Аннотация @EventListener
на методе включает обработку событий приложения.3 Получение количество незавершенных шагов из сервиса. 4 Установка количества незавершенных шагов в виде значка для элемента меню. -
Отправьте событие, используя бин
UiEventPublisher
из слушателя EntityChangedEvent:@Component public class UserStepEventListener { private final DataManager dataManager; private final UiEventPublisher uiEventPublisher; public UserStepEventListener(DataManager dataManager, UiEventPublisher uiEventPublisher) { this.dataManager = dataManager; this.uiEventPublisher = uiEventPublisher; } @EventListener public void onUserStepChangedBeforeCommit(EntityChangedEvent<UserStep> event) { User user; if (event.getType() != EntityChangedEvent.Type.DELETED) { Id<UserStep> userStepId = event.getEntityId(); UserStep userStep = dataManager.load(userStepId).one(); user = userStep.getUser(); } else { Id<User> userId = event.getChanges().getOldReferenceId("user"); if (userId == null) { throw new IllegalStateException("Cannot get User from deleted UserStep"); } user = dataManager.load(userId).one(); } uiEventPublisher.publishEventForUsers( (1) new OnboardingStatusChangedEvent(this), Collections.singleton(user.getUsername()) ); } }
1 Публикация события для всех UI всех сессий пользователя, указанного в измененной сущности UserStep
. -
Элемент меню с значком, отображающим количество незавершенных шагов