在JSF中处理表单时,是否一切都发生在一个线程中?

问题描述 投票:0回答:1

说我有这段代码

        <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实例时的可见性问题会出现问题吗?

multithreading jsf visibility jsf-2.2 safe-publication
1个回答
3
投票

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.