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

  1. 在哪里设置值绑定的值?这应该发生在解码中吗?或者应该解码做其他事情然后在encodeBegin中设置值?
  2. 从值绑定读取 - 我什么时候从值绑定读取数据?从 SubmittedValue 中读取它并将其放入值绑定中?
  3. 何时调用与所有这些相关的表单上的操作侦听器?JSF 生命周期页面都提到了在各个步骤中发生的事件,但是当仅调用命令按钮的简单侦听器时,我并不完全清楚

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

有帮助吗?

解决方案

里面有一张相当不错的图 JSF规范 这显示了请求生命周期——对于理解这些东西至关重要。

步骤是:

  • 恢复视图. 。UIComponent 树被重建。
  • 应用请求值. 。可编辑组件应该实现 EditableValueHolder。此阶段遍历组件树并调用 处理解码 方法。如果组件不像 UIData 那样复杂,那么除了调用自己的组件之外,它不会做太多事情 解码 方法。这 解码 方法除了找到它的渲染器并调用它之外没有做太多事情 解码 方法,将自身作为参数传递。渲染器的工作是获取任何提交的值并通过以下方式设置它 设置提交值.
  • 流程验证. 。此阶段调用 流程验证器 这会调用 证实. 。这 证实 方法获取提交的值,使用任何转换器对其进行转换,使用任何验证器对其进行验证,然后(假设数据通过了这些测试)调用 设定值. 。这会将值存储为局部变量。虽然此局部变量不为 null,但对于任何调用,都会返回该变量,而不是值绑定中的值 获取值.
  • 更新模型值. 。此阶段调用 流程更新. 。在输入组件中,这将调用 更新模型 这将得到 价值表达 并调用它来设置模型的值。
  • 调用应用程序. 。按钮事件侦听器等将在此处调用(如果内存可用,导航也会调用)。
  • 渲染响应. 。树通过渲染器渲染并保存状态。
  • 如果这些阶段中的任何一个失败(例如值无效),生命周期跳至渲染响应。
  • 在大多数这些阶段之后,可以触发各种事件,并根据需要调用侦听器(例如流程验证之后的值更改侦听器)。

这是事件的简化版本。请参阅规范了解更多详细信息。

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

如果污染不是问题,可以使用 Apache MyFaces 形式的开源 JSF 实现。

其他提示

动作侦听器,例如 命令按钮, ,在期间被调用 调用应用程序 阶段,这是决赛之前的最后一个阶段 渲染响应 阶段。这显示在 JSF 生命周期 - 图 1.

这是我曾经使用过的唯一框架,而组件创建是这样的深层过程。其他网络框架(无论是否在.NET世界中)都没有使它如此痛苦,这对我来说是完全无法解释的。

当您考虑目标时,JSF 背后的一些设计决策开始变得更有意义。JSF 被设计为工具化 - 它为 IDE 公开了大量元数据。JSF 不是一个 Web 框架 - 它是一个 MVP 可以用作Web框架的框架。JSF 具有高度可扩展性和可配置性 - 您可以根据每个应用程序替换 90% 的实现。

如果您只想插入额外的 HTML 控件,那么大多数内容只会让您的工作变得更加复杂。

该组件是几个输入文本(和其他)基础组件的组成,顺便说一句。

我假设 JSP-includes/基于工具的页面片段不能满足您的要求。

我会考虑使用你的 UIComponentELTag.createComponent 创建具有 UIPanel 基础的复合控件并从现有实现创建其所有子控件。(我假设您正在使用 JSP/taglib 并进行一些其他猜测。)如果现有的 UIPanel 渲染器都无法完成这项工作,您可能需要一个自定义渲染器,但渲染器很简单。

我发现的最好的文章是 Jsf组件编写, ,至于2我在哪里读取在组件中绑定的值的值


public String getBar() {  
     if (null != this.bar) {  
         return this.bar ;  
     }  
     ValueBinding _vb = getValueBinding("bar");  
     return (_vb != null) ? (bar) _vb.getValue(getFacesContext()) : null;  
}
  

这是如何进入 getValueBinding 的?在您的标签类 setProperties 方法中

  if (bar!= null) {  
         if (isValueReference(bar)) {  
             ValueBinding vb = Util.getValueBinding(bar);  
             foo.setValueBinding("bar", vb);  
         } else {  
             throw new IllegalStateException("The value for 'bar' must be a ValueBinding.");  
         }  
     }  
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top