带p:poll/push的通知系统

Öme*_*alı 12 jsf primefaces jsf-2

我已经尝试为具有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
Run Code Online (Sandbox Code Playgroud)

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

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

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

<p:socket onMessage="handleMessage" channel="/notifications" /> 
Run Code Online (Sandbox Code Playgroud)

据我所知,从这个展示示例中,这会p:socket监听notifications频道.推送代码片段是:

PushContext pushContext = PushContextFactory.getDefault().getPushContext();       
pushContext.push("/notifications", new FacesMessage(summary, detail));
Run Code Online (Sandbox Code Playgroud)

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

pushContext.push("User2/notifications", new FacesMessage("friendship request", "from User1"));
Run Code Online (Sandbox Code Playgroud)

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

谢谢你的帮助.

ere*_*can 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);
    }

}
Run Code Online (Sandbox Code Playgroud)

然后将这个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
}
Run Code Online (Sandbox Code Playgroud)

您应该将通道值赋给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>  
Run Code Online (Sandbox Code Playgroud)

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

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