代码之家  ›  专栏  ›  技术社区  ›  katiex7

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

  •  0
  • katiex7  · 技术社区  · 7 年前

    假设我有这段代码

            <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被另一个线程使用,该线程实际生成列,并在错误状态下查看hours,该怎么办?如果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;
        }
    }
    

    然而,我的问题是,如果不更改为后一种设计,在发布这个小时的实例时,由于Java中的可见性问题,使用基本的动态JSF数据表呈现时会出现问题吗?

    1 回复  |  直到 7 年前
        1
  •  3
  •   Ondřej Xicht Světlík    7 年前

    JSF运行在Servlet API之上,Servlet API在一个线程中提供一个请求,因此除非您自己引入更多线程,否则您可能希望您的代码在单个线程中运行。

    另一方面,您应该了解JSF生命周期的基本知识,以及如何访问bean属性,因为如果您不理解它,这可能会给您带来很多麻烦。

    例如,您的Java代码是否应该保持不变,向todaySchedule添加另一个引用。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;
    }