2013-04-09 75 views
12

我试图实现基本社交网络的基本通知系统p:poll在视图层和一个简单的NotificationService类从数据库获取新的通知和刷新通知列表NotificationBean这是每个用户viewscoped。类似这样的流程:p:poll/push的通知系统

-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" /> 

据我了解,从this showcase example这个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")); 

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

感谢您的帮助。

+0

你想让一个用户发送即时消息给其他用户吗? – 2013-04-12 07:03:42

+0

@RongNK,这取决于你如何理解'消息'。在这个问题中,我提到了包含通知的列表。如果user1将user2添加为朋友或对他/她的状态发表评论,则应将通知添加到user2的通知列表中,该列表可以是一个纯字符串列表或模型类列表,该列表更适合于我的实现。所以是的,那必须是立竿见影的。 – 2013-04-12 07:20:10

+0

(对不起,我的英语)好吧,我想你不想使用民意调查,所以服务器会播放按摩,每个客户端都会过滤,或者服务器必须存储客户端的地址并发送到特定的地址,我想。让亲解决你的问题:) – 2013-04-12 07:55:13

回答

8

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注释移除频道。我的解决方案中有一个用户会话通道。

我的建议是;请勿在网页上明确使用用户名。由于安全原因,这并不好。

+0

这似乎是正确的,但我仍然很少关注它的性能,有没有其他的预防措施?顺便说一句,谢谢你回答,正如你想象的那样,我要等待赏金到期,肯定会花掉蛋糕。 – 2013-04-17 09:53:52

+0

我知道JSF自身的性能问题,很多人对存储视图状态的用户存在偏见,这会降低性能。但它提供了很多功能,实际上我想亲自品尝它,当我这样做时,它应该被整齐地实现以获得最佳性能。这就是为什么我问这个问题,这就是为什么我想摆脱'p:poll'。 – 2013-04-17 10:20:06

+0

@erencan是这个应用程序范围的bean _thread safe_?由于多个并发用户,你应该知道这一点。 – oko 2013-04-17 10:28:55