Система уведомлений с p: poll/push

Я попытался внедрить базовую систему уведомлений для базовой социальной сети с p:poll на уровне представления и простым классом NotificationService, который получает новые уведомления из БД и обновляет список уведомлений NotificationBean, который viewcoped для каждого пользователя. Поток процесса аналогичен этому:

-Poll calls NotificationBean.getNewNotifications for example every 15 sec.
--getNewNotifications calls NotificationService and DAO methods
---notificationList of user is refreshed
----DataTable on view layer shows new notifications

Но проблема p:poll заключается в производительности, потому что он отправляет запрос с каждым истечением интервала.

PrimeFaces имеет PrimePush, который основан на Atmosphere Framework, он открывает веб-сокеты и кажется более подходящим для создания системы уведомлений.

Но я не знаю, какие компоненты и какие их свойства следует использовать. Он имеет компонент p:socket с свойством channel. Должен ли я использовать имена пользователей в качестве значений channel? Ниже код, поступающий из витрины PrimeFaces, и суммирует последние предложения:

<p:socket onMessage="handleMessage" channel="/notifications" /> 

Насколько я понял из этот пример витрины, этот p:socket прослушивает канал notifications. И фрагмент кода толкателя:

PushContext pushContext = PushContextFactory.getDefault().getPushContext();       
pushContext.push("/notifications", new FacesMessage(summary, detail));

Но это будет уведомлять все пользовательские страницы, мне нужен толкатель, который уведомляет конкретного пользователя. Скажем, есть 2 пользователя, и предположим, что User1 добавляет User2 в качестве друга. Должно быть, шт. например:

pushContext.push("User2/notifications", new FacesMessage("friendship request", "from User1"));

Но я не уверен, что это правильное использование для такого рода функциональных требований или нет. Учитывая масштабируемость приложения, может быть дорогостоящая стоимость открытия так много каналов в процессе.

Спасибо за помощь.

Ответ 1

Функция PrimeFaces поддерживает один или несколько каналов для нажатия. Уметь создавать частные каналы по определенным причинам; например, для каждого пользователя, как в вашем случае, вы можете создать несколько каналов. Я использовал уникальные идентификаторы для этой цели.

В принципе, я реализовал управляемый bean, который является областью действия, которая обрабатывает соответствие пользовательского канала, которое должно быть рассмотрено. Вы можете поддерживать его по-разному.

@ManagedBean
@ApplicationScoped
public class ChannelsBean {

    Map<String, String> channels = new HashMap<String, String>();

    public void addChannel(String user, String channel) {
        channels.put(user, channel);
    }

    public String getChannel(String user) {
        return channels.get(user);
    }

}

Затем введите этот bean в свою поддержку bean, который отправляет уведомления.

@ManagedBean
@SessionScoped
public class GrowlBean {

    private String channel;

    @ManagedProperty(value = "#{channelsBean}")
    private ChannelsBean channels;

    private String sendMessageUser;

    private String user;

    @PostConstruct
    public void doPostConstruction() {
        channel = "/" + UUID.randomUUID().toString();
        channels.addChannel(user, channel);
    }

    public void send() {
        PushContext pushContext = PushContextFactory.getDefault().getPushContext();

        pushContext.push(channels.getChannel(sendMessageUser), new FacesMessage("Hi ", user));
    }

    //Getter Setters
}

Вы должны указать значение канала для p: socket. Вот пример запуска страницы;

<p:growl widgetVar="growl" showDetail="true" />  

<h:form>  
    <p:panel header="Growl">  
        <h:panelGrid columns="2">  
            <p:outputLabel for="user" value="User: " />   
            <p:inputText id="user" value="#{growlBean.sendMessageUser}" required="true" />  


        </h:panelGrid>  

        <p:commandButton value="Send" actionListener="#{growlBean.send}" />  
    </p:panel>  
</h:form>  

<p:socket onMessage="handleMessage" channel="#{growlBean.channel}" />  

<script type="text/javascript">  
function handleMessage(facesmessage) {  
    facesmessage.severity = 'info';  

    growl.show([facesmessage]);  
}  
</script>  

Для проблем с масштабируемостью вы должны поддерживать активные или неактивные каналы. Вы можете удалить тот, который не находится в сеансе или неактивен в течение некоторого времени. Удалите каналы с помощью аннотации @PreDestroy, когда beans уничтожаются. В моем решении есть один канал для одного сеанса пользователя.

Мое предложение; не используйте имена пользователей явно на страницах. Это не хорошо по соображениям безопасности.