【问题标题】:Debugging JSF Life Cycle - what exactly happens in each phase调试 JSF 生命周期——每个阶段到底发生了什么
【发布时间】:2014-03-21 18:35:09
【问题描述】:

我决定完全深入研究 JSF 2.0,因为我的项目需要深入了解它。我正在阅读JSF Lifecyle Debug,这是一篇关于 JSF 生命周期的精彩文章。在阅读本文时,我有以下困惑。

  1. 如果是初始请求,则在Restore View Phase 中创建一个空视图并直接发生Render Response Phase。此时没有要保存的状态。那么render response phase 到底发生了什么?我在运行示例时有点困惑。

  2. 文章指出,检索到的输入值在Apply Request Values 阶段设置在inputComponent.setSubmittedValue() 中。如果验证和转换通过,则在inputComponent.setValue(value)inputComponent.setSubmittedValue(null) 运行中设置该值。在同一点文章指出,现在如果在下一个回发请求中更改了值,则将其与每次回发时始终为空的提交值进行比较,将调用 value change listener。这意味着如果我们甚至不更改值,因为提交的值将为空,那么 valueChangeListener 将始终被调用?我对这个说法感到困惑。有人可以详细说明一下吗?

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

  4. 检索值是什么意思?

  5. 我想知道,如果假设视图上有五个字段。 JSF 是否会列出这些值的一些集合并 Apply Request ValuesProcess Validations 阶段逐一迭代它们?

  6. 在本文的最后一点,它说明了何时使用immediate 属性。据我了解,如果在输入组件和命令组件中都设置了立即属性,它将跳过从应用请求值到调用应用程序的阶段,以获取任何不具有immediate 的属性。那么最后一条语句是什么意思是登录表单中的“忘记密码”按钮,其中包含必填且立即的用户名字段和必填但非立即的密码字段。

我知道这些是非常基本的混淆,但明确这些主题肯定有助于提高 JSF 知识。

【问题讨论】:

    标签: jsf jsf-2 lifecycle phase immediate-attribute


    【解决方案1】:

    1:那么在渲染响应阶段实际发生了什么?

    为客户端生成 HTML 输出,从 UIViewRoot#encodeAll() 开始。您可以通过右键单击在 webbrowser 中查看结果 View Source(因此不能通过右键单击,在 webbrowser Inspect Element,因为这只会显示 webbrowser 的 HTML DOM 树已基于原始 HTML 源代码和之后的所有 JavaScript 事件构建)。


    2:与提交的值进行比较,每次回发时该值始终为空

    不,它是作为实例变量保存的。 JSF 不会调用getSubmittedValue() 来比较它。


    3:我的意思是,仍然在进行转换和验证时,跳过第三阶段有什么好处?

    这在文章底部的Okay, when should I use the immediate attribute? 下得到了回答。简而言之:优先验证。如果带有immediate="true" 的组件在转换/验证时失败,那么没有immediate="true" 的组件将不会被转换/验证。


    4:检索值是什么意思?

    最终用户提交的“原始”值(最终用户在输入表单中输入的确切输入值)。这通常是String。如果您熟悉 servlet,那么很容易理解,这正是您通过request.getParameter() 获得的值。


    5:JSF 是否会列出这些值的一些集合,并在应用请求值和流程验证阶段逐一迭代它们?

    几乎。该集合已经存在于 JSF 组件树的风格中。因此,JSF 基本上迭代了一个树结构,从 FacesContext#getUIViewRoot() 开始。


    6:那么最后一条语句的含义是什么意思是登录表单中的“忘记密码”按钮,其中包含必填且立即的用户名字段和必填但非立即的密码字段。

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


    也就是说,您可能会发现以下 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));
    

    2APPLY_REQUEST_VALUES

    in.setSubmittedValue(rq.getParameter(id));
    

    3PROCESS_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);
    }
    

    4UPDATE_MODEL_VALUES

    bean.setProperty(in.getValue());
    

    5INVOKE_APPLICATION

    bean.submit();
    

    6RENDER_RESPONSE

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

    另见:

    【讨论】:

    • 一如既往的好@BalusC。太感谢了。专家的另一个出色回答。老实说,我很荣幸。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 2016-08-09
    相关资源
    最近更新 更多