2013-04-09 72 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