本文介绍了JSF生命周期和自定义组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于在JSF中开发自定义组件,我有一些事情很难理解。出于这些问题的目的,您可以假设所有自定义控件都使用了值绑定/表达式(不是文字绑定),但我也对它们的解释感兴趣。

There are a couple of things that I am having a difficult time understanding with regards to developing custom components in JSF. For the purposes of these questions, you can assume that all of the custom controls are using valuebindings/expressions (not literal bindings), but I'm interested in explanations on them as well.


  1. 我在哪里设置值绑定的值?这应该在解码中发生吗?或者应该解码做其他事情,然后在encodeBegin中设置值?

  2. 从值绑定中读取 - 何时从值绑定读取数据与从提交值读取数据并将其放入价值绑定?

  3. 关于所有这些调用的表单上的动作侦听器是什么时候? JSF生命周期页面都提到了在各个步骤中发生的事件,但是当我只调用一个名为commandbutton的简单监听器时,它并不完全清楚

我尝试了一些组合,但最终总是很难找到我认为来自对事件生命周期的基本误解的错误。

I've tried a few combinations, but always end up with hard to find bugs that I believe are coming from basic misunderstandings of the event lifecycle.

推荐答案

JSF规范中有一个非常好的图表显示请求生命周期 - 对于理解这些内容至关重要。

There is a pretty good diagram in the JSF specification that shows the request lifecycle - essential for understanding this stuff.

步骤为:


  • 还原视图。重建UIComponent树。

  • 应用请求值。可编辑组件应实现EditableValueHolder。此阶段遍历组件树并调用 processDecodes 方法。如果组件不像UIData那样复杂,除了调用自己的 decode 方法之外,它不会做太多事情。除了查找其渲染器并调用其 decode 方法并将其自身作为参数传递之外, decode 方法没有做太多工作。获取任何提交的值并通过 setSubmittedValue 设置它是渲染器的工作。

  • 流程验证。此阶段调用 processValidators ,它将调用 validate 验证方法获取提交的值,将其转换为任何转换器,使用任何验证器验证它,并(假设数据通过这些测试)调用 setValue 。这会将值存储为局部变量。虽然此局部变量不为null,但是对于对 getValue 的任何调用,都将返回该值而不是值绑定的值。

  • 更新模型值即可。此阶段调用 processUpdates 。在输入组件中,这将调用 updateModel ,它将获取 ValueExpression 并调用它来设置模型上的值。

  • 调用应用。将在此处调用按钮事件侦听器等(如果内存服务,也将导航)。

  • 渲染响应。树通过渲染器渲染并保存状态。

  • 如果这些阶段中的任何一个失败(例如值无效),生命周期将跳至渲染响应。

  • 在大多数这些阶段之后可以触发各种事件,适当地调用侦听器(比如在处理验证之后的值更改侦听器)。

  • Restore View. The UIComponent tree is rebuilt.
  • Apply Request Values. Editable components should implement EditableValueHolder. This phase walks the component tree and calls the processDecodes methods. If the component isn't something complex like a UIData, it won't do much except call its own decode method. The decode method doesn't do much except find its renderer and invokes its decode method, passing itself as an argument. It is the renderer's job to get any submitted value and set it via setSubmittedValue.
  • Process Validations. This phase calls processValidators which will call validate. The validate method takes the submitted value, converts it with any converters, validates it with any validators and (assuming the data passes those tests) calls setValue. This will store the value as a local variable. While this local variable is not null, it will be returned and not the value from the value binding for any calls to getValue.
  • Update Model Values. This phase calls processUpdates. In an input component, this will call updateModel which will get the ValueExpression and invoke it to set the value on the model.
  • Invoke Application. Button event listeners and so on will be invoked here (as will navigation if memory serves).
  • Render Response. The tree is rendered via the renderers and the state saved.
  • If any of these phases fail (e.g. a value is invalid), the lifecycle skips to Render Response.
  • Various events can be fired after most of these phases, invoking listeners as appropriate (like value change listeners after Process Validations).

这是一个有点简化的事件版本。有关详细信息,请参阅规范。

This is a somewhat simplified version of events. Refer to the specification for more details.

我会质疑为什么要编写自己的UIComponent。这是一项非常重要的任务,需要深入了解JSF架构才能使其正确。如果你需要一个自定义控件,最好创建一个具有等效渲染器扩展现有UIComponent(如HtmlInputText)的具体控件。

I would question why you are writing your own UIComponent. This is a non-trivial task and a deep understanding of the JSF architecture is required to get it right. If you need a custom control, it is better to create a concrete control that extends an exisiting UIComponent (like HtmlInputText does) with an equivalent renderer.

如果污染不是一个问题,有一个Apache MyFaces形式的开源JSF实现。

If contamination isn't an issue, there is an open-source JSF implementation in the form of Apache MyFaces.

这篇关于JSF生命周期和自定义组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-28 05:52