带p:poll / push的通知系统

时间:2013-04-09 13:52:47

标签: jsf jsf-2 primefaces

我尝试在视图层上使用p:poll的基本社交网络和一个简单的NotificationService类实现基本通知系统,该类从DB获取新通知并刷新{{}的通知列表{1}}是每个用户的视图编组。与此类似的流程:

NotificationBean

-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 关注的是它的性能,因为它会在每个时间间隔到期时发送一个查询。

PrimeFaces有PrimePush基于Atmosphere Framework,它打开网络套接字,似乎更适合创建通知系统。

但我不知道应该使用哪些组件及其属性。它具有p:poll组件,具有p:socket属性。我应该将用户名用作channel值吗?下面来自PrimeFaces的代码展示并总结了最后的句子:

channel

据我所知this showcase example这个<p:socket onMessage="handleMessage" channel="/notifications" /> p:socket频道。推送代码片段是:

notifications

但这会通知所有用户页面,我需要一个通知特定用户的推送器。假设有2个用户并假设User1将User2添加为朋友。必须有某事。那样:

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

但我不确定这是否适用于此类功能要求。考虑到应用程序的可扩展性,每个进程打开如此多的通道可能会产生昂贵的成本。

感谢您的帮助。

1 个答案:

答案 0 :(得分:8)

PrimeFaces推送支持一个或多个频道推送。能够出于特定原因创建私人频道;例如,对于每个用户而言,您可以创建多个频道。我为此目的使用了独特的ID。

基本上,我已经实现了一个托管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>  

对于可伸缩性问题,您应该维护活动或非活动通道。您可以删除一段时间未处于会话或非活动状态的会话。当bean正在销毁时,使用@PreDestroy注释删除通道。在我的解决方案中,有一个用户会话通道。

我的建议是;不要在页面上明确使用用户名。出于安全原因,它并不好。