调试JSF生命周期 - 每个阶段到底发生了什么

13

我的项目需要深入了解JSF 2.0,因此我决定彻底研究它。我正在阅读JSF Lifecyle Debug,这是一篇关于JSF生命周期的很好的文章。在阅读这篇文章时,我有以下疑问。

  1. 如果这是一个初始请求,在还原视图阶段将创建一个空视图,并直接进入渲染响应阶段。此时没有状态可保存。那么在渲染响应阶段中实际发生了什么?当我运行示例时,有点困惑。

  2. 文章指出,Apply Request Values阶段会在inputComponent.setSubmittedValue()中设置检索到的输入值。如果验证和转换通过,则该值将在inputComponent.setValue(value)中设置,并且inputComponent.setSubmittedValue(null)将运行。在同一点上,文章指出,如果在下一个后续请求中更改了值,则与每个后续请求上始终为空的提交值进行比较,将调用valueChangeListener。这意味着,即使我们没有更改值,由于提交值将始终为空,valueChangeListener也将总是被调用?我对这个说法感到困惑。有人能详细解释一下吗?

  3. 文章指出了immediate属性的使用。如果在输入组件上设置了immediate属性,则理想情况下会跳过Process Validation Phase,但所有转换和验证都会在Apply Request Values中进行。我的观点是,在转换和验证仍在进行时,跳过第三阶段的好处是什么?

  4. 检索到的值是什么意思?

  • 我想知道,如果一个视图上有五个字段,JSF 是否会将这些值的某个集合制作成列表,并在应用请求值处理验证阶段逐个迭代它们?

  • 在本文最后所述的使用 immediate 属性的情况下。根据我的理解,如果在输入组件和命令组件中都设置了 immediate 属性,则对于没有immediate属性的任何属性,它将跳过从应用请求值到调用应用的阶段。那么最后一句话“密码忘记”按钮在具有必填且立即用户名字段和必填但非立即密码字段的登录表单中是什么意思?

  • 我知道这些是非常基础的疑问,但对这些主题的清晰度肯定有助于加强 JSF 知识。

    1个回答

    18

    渲染响应阶段的实际操作是什么?从UIViewRoot#encodeAll()开始为客户端生成HTML输出。您可以通过右键单击Web浏览器中的“查看源代码”(而不是右键单击Web浏览器中的“检查元素”,因为后者只会显示Web浏览器基于原始HTML源代码和所有JavaScript事件构建的HTML DOM树)来查看结果。


    与提交的值进行比较,每次回发都将为null。


    这在文章底部的Okay, when should I use the immediate attribute?下有答案。简而言之:优先验证。如果具有immediate="true"属性的组件在转换/验证失败,则没有immediate="true"属性的组件将无法转换/验证。


    “检索到的值”是指最终用户提交的“原始”值(最终用户在输入表单中输入的确切输入值)。这通常是一个字符串。如果您熟悉Servlet,则很容易理解它正好是通过request.getParameter() 获得的值。


    几乎如此。JSF中的集合已经存在于JSF组件树中。因此,JSF基本上遍历树结构,从FacesContext#getUIViewRoot()开始。


    这样,您就可以重用登录表单进行“密码忘记”情况。如果您提交“登录”按钮,那么显然必须验证用户名和密码字段。但是,如果您提交了“密码忘记”按钮,则不应该验证密码字段。


    此外,您可能也会发现下面的JSF阶段/生命周期速查表对于快速参考也非常有用:


    • fc = FacesContext
    • vh = ViewHandler
    • in = UIInput
    • rq = HttpServletRequest
    • id = in.getClientId(fc);

    1 RESTORE_VIEW

    String viewId = rq.getServletPath();
    fc.setViewRoot(vh.createView(fc, viewId));
    

    2 APPLY_REQUEST_VALUES

    :应用请求值。
    in.setSubmittedValue(rq.getParameter(id));
    

    3 PROCESS_VALIDATIONS

    Object value = in.getSubmittedValue();
    try {
       value = in.getConvertedValue(fc, value);
       for (Validator v : in.getValidators())
          v.validate(fc, in, value);
       }
       in.setSubmittedValue(null);
       in.setValue(value);
    } catch (ConverterException | ValidatorException e) {
       fc.addMessage(id, e.getFacesMessage());
       fc.validationFailed(); // Skips phases 4+5.
       in.setValid(false);
    }
    

    4 UPDATE_MODEL_VALUES

    :更新模型数值。
    bean.setProperty(in.getValue());
    

    5 INVOKE_APPLICATION

    bean.submit();
    

    6 RENDER_RESPONSE

    vh.renderView(fc, fc.getViewRoot());
    

    参见:


    1
    一如既往的棒,@BalusC。非常感谢你。又一位专家给出了优秀的答案。我真的很荣幸。 - benz

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接