Ö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)
但我不确定这是否是这种功能要求的正确用法.考虑到应用程序的可扩展性,每个进程打开如此多的通道可能会产生昂贵的成本.
谢谢你的帮助.
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注释删除通道.在我的解决方案中,一个用户会话有一个通道.
我的建议是; 不要在页面上明确使用用户名.出于安全原因这不好.