本文介绍了JSF:为什么在请求范围内的POST REDIRECT GET下提交表单期间,在应用请求值阶段期间调用了呈现中的空测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题来自

以下,元素是具有名称和ID的@Entity.一个view.xhtml JSF页面将id用作viewParam并使用@ManagedBean @RequestScoped ElementController的setID(Long id)触发按ID从数据库加载相应的Element(在问题中没有进一步的作用),并且找到了这个将Element设置为当前"可用元素(由于历史原因,名称稍有不同)为Element getSelected().

In the following an Element is an @Entity with a name and id. A view.xhtml JSF page takes the id as a viewParam and uses setID(Long id) of the @ManagedBean @RequestScoped ElementController to trigger loading of the corresponding Element by id from database (that plays no further role in the question) and this found Element is set as the 'current' Element available (for historical reasons by a slightly different name) as Element getSelected().

view.xhtml页面执行呈现的属性测试#{非空elementController.selected},并具有ah:commandButton,其操作执行一个faces-redirect,并将id用作查询参数,并返回到view.xhtml页面.

The view.xhtml page performs a rendered attribute test #{not empty elementController.selected}, and has a h:commandButton with action that performs a faces-redirect, along with the id as query parameter, back to the view.xhtml page.

由于某种原因,我不完全了解,在提交表单时,在设置viewParam ID之前(因此在当前/之前,在申请请求阶段和流程验证阶段都调用了测试(并因此调用了getSelected).可以在更新模型值阶段找到并设置选定的元素.

For some reason I do not fully understand, on form submission the test (and thus getSelected) is invoked in both the apply request phase and the process validations phase, before the viewParam id can be set (and thus before the current/selected Element can be found and set) in the update model values phase.

大大简化的view.xhtml页面是:

The greatly abbreviated view.xhtml page is:

<f:view>
 <f:metadata>
    <f:viewParam name="id" value="#{elementController.id}"/>
 </f:metadata>
</f:view>
<h:body>
 <h:form>
   <h:panelGroup rendered="#{not empty elementController.selected}">
       <h:outputText value="#{elementController.selected.name}"/>
   </h:panelGroup>

   <h:commandButton value="Apply" action="#{elementController.action}" />

 </h:form>
</h:body>

(上面已经失去了表单提交的意义,但是对于这个问题并不重要.)

(The sense of the form submission is lost above, but it does not matter for the this question.)

ElementController扩展了RequestController:

ElementController extends RequestController:

public void setId(Long id) {
log_debug("setId","id",id);
if (id != null) {
    this.id = id;
    T found = (T) getAbstractFacade().find(id);
    if (found == null) {
        String $error = "No object with id(" + id + ") found for class " + getManagedClass().getSimpleName();
        log_error($error);
    }
    setCurrent(found);
 }
}

public T getSelected() {
  log_debug("getSelected","current",current);
  if (current == null) {
    log_warn("getSelected","null current Element");
   }
 return current;
}

public Object action() {
    String $i = "action";
    log_debug($i);
    if (current==null) {
        log_warn($i, "can't generate action outcome for null current element");
        return null;
    }
    return "/view?faces-redirect=true&id="+current.getId();
 }

现在提交表单时,由于测试#{非空elementController.selected,因此getSelected()恰好被调用两次,当current == null时,一次在应用请求值阶段,一次在过程验证阶段. }得益于view.xhtml中的viewParam,才可以进行id的设置(从而可以加载Element实体).

Now on form submission, getSelected() happens to get called twice, and when current==null, once during the apply request values phases and once during the process validations phase, due to the test #{not empty elementController.selected} before the setting of the id (and thus loading of the Element entity) can occur thanks to the viewParam in the view.xhtml.

问题是,为什么在应用请求阶段和流程验证阶段完全调用了render == {not not empty elementController.selected}?

The question is, why is the rendered=#{not empty elementController.selected} invoked at all during the apply request phase and process validations phase ?

在这些阶段中,当我使用id参数对view.xhtml进行初始GET加载时,仅在表单提交POST以及随后的重定向和GET期间不调用它.

It is not invoked during those phases when I perform an initial GET load of the view.xhtml with id parameter, only during a form submission POST and subsequent redirect and GET.

推荐答案

回发后两次查询rendered属性的原因是因为JSF在每个阶段都遍历了组件树.

The reason that the rendered attribute is consulted twice or more after a post back is because JSF traverses the component tree in each phase.

名称"rendered"可能不是最好的名称,因为它不仅使有条件应用其组件的渲染成为条件,而且实际上通常对其进行处理.

The name 'rendered' is perhaps not the best possible name, as it doesn't just make rendering of the component to which it applies conditional, but actually processing it in general.

首先咨询了应用请求值",以查看是否应对该组件及其子级进行处理以将那些请求值应用于它们.在过程验证"中再次进行了协商,因为它的值可能在各个阶段之间有所变化.

It's consulted in the first place for 'apply request values' to see if that component and its children should be processed to have those request values applied to them. It's consulted again in 'process validations', since its value might have changed between phases.

在执行初始GET加载的那些阶段期间"不会调用它,因为在执行GET时,在这些阶段中不会遍历组件树(仅处理元数据,这就是放置视图参数的原因在特殊的元数据部分).

It's not invoked 'during those phases when I perform an initial GET load', because when you perform a GET the component tree isn't traversed in those phases (only the metadata is processed, which is the reason view params are put in a special metadata section).

为了使从GET请求中收到的id在回发后的操作方法中可用,您最好为后备bean使用视图范围(@ViewScoped).

In order to make the id that you received from the GET request available in the action method after the post back, you'd best use the view scope (@ViewScoped) for your backing bean.

这篇关于JSF:为什么在请求范围内的POST REDIRECT GET下提交表单期间,在应用请求值阶段期间调用了呈现中的空测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-30 06:50