在仪表板上每个用户都可以看到一些基本统计信息。让我们以"最后一次登录"日期为例。(但是还有更多的统计/值/设置要显示)
XHTML文件看起来像这样简化:
<h:outputText value="statisticController.lastLoginDate()" />
Bean本身使用@Inject
获取会话,因此获取当前用户:
@Named
@RequestScoped
public StatisticController{
@Inject
private mySessionBean mySession;
@PostConstruct
private void init(){
//load stats for mySession.currentUser;
}
}
现在,我想生成一个列表,例如某个角色可以查看所有用户的值。因此,我不能再使用会话注入,因为现在需要为多个用户生成StatisticController。
拥有常规类,这不会是一个大问题-将userEntity添加到构造函数中。在JSF中解决这个问题的"最佳实践"是什么?
如果我将StatisticController修改为如下内容:
@Named
@RequestScoped
public StatisticController{
public void init(User user){
//load stats for user;
}
}
我当然需要手动调用init(user)
。如何在XHTML文件中的迭代中实现这一点?
我可以重构它,让valueLoading发生在实际的getter方法中,并像这样迭代:
<ui:repeat var="user" value="#{userDataService.getAllUsers()}">
<h:outputText value="statisticController.lastLoginDate(user)" />
...
</ui:repeat>
但是我需要单独加载"every"值,这很糟糕。
所以像这样的方式会"更好":
<ui:repeat var="user" value="#{userDataService.getAllUsers()}">
statisticController.init(user);
<h:outputText value="statisticController.lastLoginDate()" />
...
</ui:repeat>
然而这看起来也不太舒服。进一步做这样的事情,将移动几乎"所有"后端东西到渲染响应阶段,这是错误的感觉。
有什么想法/提示如何以一种不像"变通"的方式解决这个问题吗?
创建一个包含这些模型的新模型。
public class UserStatistics {
private User user;
private Statistics statistics;
// ...
}
这样你就可以直接用
public class UserStatisticsBacking {
private List<UserStatistics> list;
@EJB
private UserService userService;
@EJB
private StatisticsService statisticsService;
@PostConstruct
public void init() {
list = new ArrayList<UserStatistics>();
for (User user : userService.list()) {
list.add(new UserStatistics(user, statisticsService.get(user)));
}
}
// ...
}
(最好是在新的UserStatisticsService
中执行)
<ui:repeat value="#{userStatisticsBacking.list}" var="userStatistics">
<h:outputText value="#{userStatistics.user.name}" />
<h:outputText value="#{userStatistics.statistics.lastLoginDate}" />
...
</ui:repeat>
使用BalusC提出的包装模型的另一种选择是存储包含模型数据的两个单独列表。使用这种方法,您不需要引入修改。
按照这条路线,您将使用<ui:repeat>
迭代一个列表,并确保两个列表的大小相等,通过索引获得第二个列表元素,这反过来又可以通过导出迭代状态变量的varStatus
属性获得。
<ui:param name="stats" value="#{bean.stats}/>
<ui:repeat value="#{bean.users}" var="user" varStatus="status">
<h:outputText value="#{user}/>
<h:outputText value="#{stats[status.index]}/>
</ui:include>
列表的填充可以在PostConstruct
方法中预先完成:
private List<User> users;
private List<Statistic> stats;
@PostConstruct
public void init() {
users = userService.list();
stats = statService.list();
}