Reusing of Beans



在仪表板上每个用户都可以看到一些基本统计信息。让我们以"最后一次登录"日期为例。(但是还有更多的统计/值/设置要显示)

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();
}

相关内容

  • 没有找到相关文章