Я работаю над проектом, который использует vaadin в качестве внешнего интерфейса и Spring-boot для внутреннего интерфейса. В этом приложении у меня есть определенный вариант использования, когда группа пользователей (операторов) работает на разных станциях, где они могут генерировать события, о которых должна быть уведомлена другая другая группа пользователей (супевизоров), но только для станций, которым они назначены. Как правило, это не имеет большого значения, но я хочу использовать веб-push-уведомления, чтобы уведомлять руководителей, когда происходит новое событие.
Я начал немного читать об API уведомлений и удалось создать представление в vaadin, которое проверяет, было ли браузеру предоставлено разрешение на отправку уведомлений (в моем примере в Windows 10), и если разрешение еще не предоставлено, отобразить кнопку, чтобы запросить это. если разрешение было предоставлено, кнопка будет скрыта, а метка будет подтверждать, что разрешение было предоставлено. одновременно отправляется тестовое уведомление (чтобы я мог проверить, работает ли оно). Пока все работает отлично.
Я реализовал все, используя смесь java / vaadin и собственного java-скрипта
window.sendNotification = function(element, body, icon, title, type, id) {
var options = {
body: body,
icon: icon
}
var notification = new Notification(title, options);
notification.onclick = (e) => element.$server.notificationClicked(type, id);
}
window.checkNotificationPermission = function() {
return Notification.permission;
}
window.askNotificationPermission = function(element) {
function handlePermission(permission) {
element.$server.permissionAsked(permission);
}
// Let's check if the browser supports notifications
if (!('Notification' in window)) {
console.log("This browser does not support notifications.");
} else {
if (checkNotificationPromise()) {
Notification.requestPermission()
.then((permission) => {
handlePermission(permission);
})
} else {
Notification.requestPermission(function(permission) {
handlePermission(permission);
});
}
}
}
function checkNotificationPromise() {
// safari supported permission or all other browsers?
try {
Notification.requestPermission().then();
} catch (e) {
return false;
}
return true;
}
Это сторона js, в java / vaadin я аннотировал представление с помощью @PWA (используя сгенерированный sw.js и манифест), @Push и @JsModule для включения кода js. Кроме того, я вызываю каждую функцию js с помощью page.executeJs (), например, так:
Page page = UI.getCurrent().getPage();
page.executeJs("askNotificationPermission($0)", this.getElement());
Я также предоставляю методы обратного вызова, которые обрабатывают, когда разрешение было предоставлено или когда было щелкнуто уведомление. Например:
@ClientCallable
private void permissionAsked(String permission) {
sendSuccessNotification();
permissionChecked(permission);
}
пока здесь все работало нормально.
Теперь моя большая проблема заключается в том, как я могу автоматически уведомлять каждого пользователя (некоторые из них могут даже войти в систему на разных машинах, например, на ПК и смартфоне). Я подумал о том, чтобы запустить другой поток в представлении и позволить ему опрашивать серверную часть на предмет новых уведомлений:
нравится:
@Override
protected void onAttach(AttachEvent attachEvent) {
// Start the data feed thread
thread = new NotificationThread();
thread.start();
}
@Override
protected void onDetach(DetachEvent detachEvent) {
// Cleanup
thread.interrupt();
thread = null;
}
private class NotificationThread extends Thread {
@Override
public void run() {
try {
while (true) {
Thread.sleep(10000); // update every 10 seconds
List<ResponseNotification> findNewNotifications = notificationController.findNewNotifications();
if (findNewNotifications.size() > 1) {
sendGeneralNotification("You have new notifications", "New Notifications!", NavigationTarget.NOTIFICATIONS, "");
} else if (findNewNotifications.size() == 1) {
sendGeneralNotification("An operator requires your attention", "Operator", NavigationTarget.OPERATOR, notification.operator.id);
}
}
} catch (InterruptedException e) {
// ...
// handle
}
}
}
Самая большая проблема в этом подходе заключается в том, что аутентификация больше не доступна в бэкэнде, так как она была вызвана из другого потока, и поэтому SecurityContextHolder.getContext().getAuthentication()
вернет null. Но я также не уверен, что общий подход является разумным, поскольку представление всегда должно быть открытым, и я чувствую, что опрос каждые 10 секунд может привести к ненужной нагрузке на серверную часть, когда будет больше, чем просто группа супервизоров.
события хранятся в моей базе данных, и я также хочу отправить электронное письмо в дополнение к уведомлению, поэтому было бы идеально, если бы существовал способ отправки уведомлений с бэкэнда и их отправки клиентам, пока события обрабатываются в любом случае. возможно, у кого-то уже есть опыт и он может помочь мне найти решение этой проблемы.
заранее спасибо!