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

ben*_*enz 10 lifecycle jsf phase jsf-2 immediate-attribute

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

  1. 如果是初始请求,Restore View Phase则会在空视图中创建并直接Render Response Phase发生.此时没有可以保存的州.render response phase那时究竟发生了什么?我在运行这个例子时感到很困惑.

  2. 该文章指出,检索输入值被设置在inputComponent.setSubmittedValue()Apply Request Values相位.如果验证和转换通过,则设置值inputComponent.setValue(value)inputComponent.setSubmittedValue(null)运行.在同一篇文章中指出,现在如果在下一个回发请求中,值被更改,则将其与提交的值进行比较,该值在每个帖子后面将始终为null,alue change listener将调用v .这意味着,如果,我们不更改值,因为submittedValue将为null,将始终调用valueChangeListener?我对此声明感到困惑.有人可以详细说明吗?

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

  4. 该术语检索值的含义是什么?

  5. 我想知道,如果让我们说视图上有五个字段.JSF是否列出了这些值的某些集合,Apply Request ValuesProcess Validations逐步对它们进行迭代?

  6. 在本文的最后一点说明,何时使用immediate属性.根据我的理解,如果在输入组件和命令组件中都设置了immediate属性,那么对于没有的任何属性,它将跳过从Apply Request Values to Invoke Application的阶段immediate.那么最后一个语句在登录表单中是什么意思是"忘记密码"按钮,其中包含必需的即时用户名字段和必需但非直接的密码字段.

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

Bal*_*usC 14

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

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


2:将其与提交的值进行比较,该值在每个帖子上始终为空

不,它被保存为实例变量.JSF没有打电话getSubmittedValue()来比较它.


3:我的观点是,当转换和验证发生时,跳过第三阶段的优势是什么?

这可以在文章的底部回答,好的,我什么时候应该使用immediate属性?.简而言之:优先验证.如果immediate="true"转换/验证失败的组件,则不会转换/验证组件immediate="true".


4:术语检索值意味着什么?

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


5:JSF是否列出了这些值的一些集合,并且Apply Request Values和Process Validations阶段逐个迭代它们?

几乎.该集合已经存在于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));
Run Code Online (Sandbox Code Playgroud)

2 APPLY_REQUEST_VALUES

in.setSubmittedValue(rq.getParameter(id));
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

4 UPDATE_MODEL_VALUES

bean.setProperty(in.getValue());
Run Code Online (Sandbox Code Playgroud)

INVOKE_APPLICATION

bean.submit();
Run Code Online (Sandbox Code Playgroud)

6 RENDER_RESPONSE

vh.renderView(fc, fc.getViewRoot());
Run Code Online (Sandbox Code Playgroud)

也可以看看: