重复使用豆类

时间:2013-04-10 10:10:07

标签: jsf javabeans

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

XHTML文件看起来像这样简单:

<h:outputText value="statisticController.lastLoginDate()" />

Bean本身使用@Inject来获取Session,因此使用当前用户:

@Named
@RequestScoped
public StatisticController{
    @Inject
    private mySessionBean mySession;

    @PostConstruct
    private void init(){
       //load stats for mySession.currentUser;
    }
}

现在,我想生成一个List,例如某个角色可以查看所有用户的值。因此我不能再使用Session Inject,因为现在需要为多个用户生成StatisticController。

使用常规类这不会是一个大问题 - 将userEntity添加到构造函数中。在JSF中解决这个问题的“最佳实践”是什么?

如果我将StatisticController修改为这样的东西:

@Named
@RequestScoped
public StatisticController{

    public void init(User user){
       //load stats for user;
    }
}

我当然需要手动拨打init(user)。如何在XHTML文件的迭代中实现?

我可以重构它,以便在实际的getter方法中发生valueLoading,并像这样迭代:

<ui:repeat var="user" value="#{userDataService.getAllUsers()}">
    <h:outputText value="statisticController.lastLoginDate(user)" />        
    ...
</ui:repeat>

但是我需要加载“每个”值分开,这很糟糕。

所以这样的方式会“更好”:

<ui:repeat var="user" value="#{userDataService.getAllUsers()}">
    statisticController.init(user);
    <h:outputText value="statisticController.lastLoginDate()" />        
    ...
</ui:repeat>

然而,这看起来也不舒服。进一步做这样的事情,将几乎“全部”后端东西移动到渲染响应阶段,这是错误的。

任何Ideas / Tipps如何以一种不像“变形方式”的方式解决这个问题?

2 个答案:

答案 0 :(得分:2)

创建一个包装这些模型的新模型。

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>

答案 1 :(得分:0)

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