通知系统带有p:poll/push



我尝试为一个基本的社交网络实现基本的通知系统,p:poll在视图层和一个简单的NotificationService类,它从DB获得新的通知,并刷新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

但是p:poll关心的是它的性能,因为它在每个间隔过期时发送一个查询。

PrimeFaces有基于Atmosphere框架的PrimePush,它打开了web sockets,似乎更适合创建通知系统。

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

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

据我所知,从这个演示示例中,p:socket监听notifications通道。push代码片段为:

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"));

但我不确定这是否是这种功能需求的正确用法。考虑到应用程序的可扩展性,每个进程打开如此多的通道可能会带来昂贵的成本。

谢谢你的帮助。

PrimeFaces push支持一个或多个通道推送。能够为特定原因创建专用通道;例如,对于像您这样的每个用户,您可以创建多个通道。为此,我使用了唯一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注释删除通道。在我的解决方案中,一个用户会话有一个通道。

我的建议是;不要在页面上明确地使用用户名。从安全角度考虑,这是不好的。

相关内容

  • 没有找到相关文章

最新更新