gpt4 book ai didi

jsf - 通知系统 p :poll/push

转载 作者:行者123 更新时间:2023-12-02 10:08:11 25 4
gpt4 key购买 nike

我尝试通过 View 层上的 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 有 PrimePush它基于Atmosphere Framework,它打开网络套接字,似乎更适合创建通知系统。

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

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

据我了解this showcase examplep:socket 监听通知 channel 。推送器代码片段是:

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

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

感谢您的帮助。

最佳答案

PrimeFaces推送支持一个或多个 channel 推送。能够出于特定原因创建私有(private) channel ;例如,对于您的情况,每个用户都可以创建多个 channel 。我为此目的使用了唯一的 ID。

基本上,我已经实现了一个托管 bean,它是应用程序范围的,用于处理应该考虑的用户 channel 匹配。您可以通过不同的方式维护它。

@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 注入(inject)到发送通知的支持 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
}

您应该将 channel 值赋予 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>

对于可扩展性问题,您应该维护事件或非事件 channel 。您可以删除不在 session 中或一段时间不活动的 session 。当 bean 销毁时,使用 @PreDestroy 注释删除 channel 。在我的解决方案中,一个用户 session 有一个 channel 。

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

关于jsf - 通知系统 p :poll/push,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15903816/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com