我有一个使用jsf和prime faces的系统。
我想:
在主页上显示所有已记录的用户名称及其实时总数。
在每个页面上显示相同但与每个特定页面相关的内容。我希望用户知道谁在同一时间查看同一页面。
需要查看范围,因为某些页面包含敏感信息。
提前致谢。
答案 0 :(得分:6)
创建一个@ApplicationScoped
bean存储您要在用户之间共享的所有信息。然后,您可以在@ViewScoped
中获取与用户的私有信息相关的信息。请记住,您可以从同一视图中引用它们。
话虽如此,主要的挑战是知道用户何时以某种方式完成会话。从JSF的角度来看,我理解这是不可能知道的,所以诀窍是更进一步,并在解释HttpSessionBindingListener
时使用here。
让我们提供@ApplicationScoped
bean的基本实现(假设您正在使用JSF 2和EL 2.2,它允许您将params传递给服务器方法):
@ManagedBean
@ApplicationScoped
public class GeneralInfo{
List<UserBean> onlineUsers;
//Getters and setters
public int numberUsersWathingThis(String viewId){
int result = 0;
for (UserBean ub : onlineUsers){
if (ub.getCurrentViewId().equals("viewId")){
result++;
}
}
return result;
}
}
您可以在此处存储实际在线的用户列表。假设每个用户都有一个String
属性指定显示的当前视图,我们需要一个简单的迭代来检索当前有多少用户在指定的视图ID中。
然后让我们假设你有一个@SessionScoped
bean,它也保留了当前登录的用户。当HttpSession开始时创建该bean,并在用户登录时创建当前UserBean。UserBean
将找到GeneralInfo
bean并将其注入其中。
@ManagedBean
@SessionScoped
public class SessionBean{
UserBean userBean;
//Create your UserBean when user logs into the application
public void setCurrentPage(String currentViewId){
userBean.setCurrentViewId(currentViewId);
}
}
UserBean
的实施,需要实施HttpSessionBindingListener
才能在从HttpSession
移除之前得到通知。如果你看一下,这个通知将触发一个UserBean#valueUnbound
方法调用,bean从@ApplicationScoped
托管bean中自行删除。这允许GeneralInfo
bean知道用户实际在线。
public class UserBean implements HttpSessionBindingListener{
@ManagedProperty(value="#{generalInfo}")
GeneralInfo generalInfo;
@PostConstruct
public void postConstruct(){
generalInfo.addUser(this);
}
@Override
void valueUnbound(HttpSessionBindingEvent event){
generalInfo.removeUser(this);
}
//Getter and Setters
}
在那之后,作为最后一个挑战,我们想知道当前用户正在观看什么。解决这个问题的一种简单方法是使用管理当前视图的@ViewScoped
bean来更新存储在UserBean
bean中的@SessionScoped
。因此,让我们访问当前的@ViewScoped
bean并更新用户看到的内容:
@ManagedBean
@ViewScoped
public class Page1Info{
@ManagedProperty(value="#{sessionBean}")
SessionBean sessionBean;
public void initialize(ComponentSystemEvent event){
sessionBean.setCurrentPage("page1.xhtml");
}
}
page1Info#initialize
方法被称为preRenderView
事件(对JSF 2.2+使用f:viewAction
)。所以最后会有某种观点:
<f:metadata>
<f:event type="preRenderView"
listener="#{page1Info.initialize}" />
</f:metadata>
<h:outputText value="There are #{fn:length(generalInfo.onlineUsers)} users online" />
<h:outputText value="There are #{numberUsersWathingThis("page1.xhtml")} users watching this" />