说我有这段代码
<p:dataTable styleClass="scheduleTable" value="#{todaySchedule.hours}" var="hour">
<p:column headerText="Hour" styleClass="hourColumn" >
#{hour.time}
</p:column>
</p:dataTable>
在一个名为todaySchedule的类中,有一个方法
public List<Hour> getHours() {
final List<Hour> hours = IntStream.range(0, Hour.TIME.values().length)
.mapToObj($ -> new Hour()).collect(Collectors.toList());
for (int i = 0; i < 5; i++) {
hours.get(i).setHour(1);
}
return hours;
}
这是小时课
public class Hour {
private int time;
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
}
现在,我不确定JSF在幕后做了什么来使这个动态dataTable数据迭代完成小时列表可能,但我认为如果这一切都发生在一个线程中,那么它是可以的。但是,如果在幕后,getHours用于另一个实际执行生成列的线程并且看到Hour处于错误状态?如果getHours()方法是,则可以避免这种情况
public List<Hour> getHours() {
final List<Hour> hours = new ArrayList<>();
for (int i = 0; i < 5; i++) {
hours.add(new Hour(i + ""));
}
return hours;
}
with the corresponding Hour class being
public class Hour {
private final int time;
public Hour(int time) {
this.time = time;
}
public int getTime() {
return time;
}
}
但是,我的问题是,如果它没有改为后一种设计,那么在使用基本的动态JSF dataTable渲染时,由于Java发布此Hour实例时的可见性问题会出现问题吗?
JSF运行在Servlet API之上,它在一个线程中提供一个请求,因此除非您自己引入更多线程,否则您可能希望您的代码在单个线程中运行。
另一方面,您应该了解JSF生命周期的基础知识以及如何访问bean属性,因为如果您不理解它可能会给您带来很多麻烦。
例如,如果您的Java代码保持不变,那么将nowSchedule.hours的另一个引用添加到您的JSF将导致getter被调用两次,从而生成两次内容。这可能会很快变得非常混乱,所以做一些“缓存”是一件好事。我个人使用这种方法:
private List<Hour> hours = null;
private void initHours() {
this.hours = new LinkedList<>();
// Fill hours here
}
public List<Hour> getHours() {
if (this.hours == null) {
initHours();
}
return this.hours;
}
您必须小心,但在JSF生命周期的哪个阶段,您必须这样做。例如,如果您在表单处理方法中更改影响列表生成的数据,则列表可能已经从还原视图阶段“缓存”,并且在渲染视图阶段开始时不会反映更改。在这种情况下,您应该知道缓存并在需要重新加载时清除列表。
public void saveHours() {
// Save the data, do whatever you need to do
// This will ensure re-initializing the list on the next call
this.hours = null;
}