3

我很好奇 JSF 是如何知道我单击了按钮并执行了一些操作,甚至可以使用参数调用操作侦听器。我可以想象服务器会注意到状态和 EL 并调用方法。

示例 1:

<form>
   <p:commandButton actionListener="{bean.do_something(bean.info)}" />
</form>

示例 2:

<form>
     <h:datatable values=... var="myvar">
        <h:column>
           <p:commandButton actionListener="{bean.do_something(myvar.info)}" />
        </h:column>
     </h:datatable>
</form>
4

1 回答 1

7

在应用请求值阶段,执行组件树decode()中所有实例的方法。UIComponent这是检查和收集必要的 HTTP 请求参数的地方。在UIInput组件(<h:inputText>和朋友)的情况下,获取提交的值。如果是UICommand组件(<h:commandButton>和朋友),ActionEvent则已排队。

万一<p:commandButton>发生了神奇的事情,在下面提取了源代码CommandButtonRenderer#decode()的相关部分(行号来自 PrimeFaces 3.5):

34  public void decode(FacesContext context, UIComponent component) {
35      CommandButton button = (CommandButton) component;
36      if(button.isDisabled()) {
37          return;
38      }
39         
40      String param = component.getClientId(context);
41      if(context.getExternalContext().getRequestParameterMap().containsKey(param)) {
42          component.queueEvent(new ActionEvent(component));
43      }
44  }

如果您熟悉基本的 HTML,您应该已经知道name=value每个输入元素的对和仅封闭表单的按下按钮作为请求参数发送到服务器。PrimeFaces 命令按钮基本上生成以下 HTML,

<button type="submit" name="formId:buttonId" ... />

从哪里formId:buttonId打印UIComponent#getClientId()。正是这个值被用作 HTTP 请求参数名称(HTTP 请求参数值是按钮的标签,但这里不再相关)。如果您熟悉JSF 在其之上运行的基本 Servlets,那么您也应该已经知道请求参数可以通过 获得HttpServletRequest#getParameter(),包括name=value按钮对。这允许区分按下的按钮

正如你在上面的decode()方法中看到的,这个UIComponent#getClientId()值也被用来检查 HTTP 请求参数映射是否包含参数名称。如果是这样,那么 anActionEvent将被排队,最终在调用应用程序阶段被调用。

至于 EL 论点,它实际上不是火箭科学。整个 EL 表达式只是在调用应用程序阶段执行。它不是在生成表单的 HTML 输出期间执行的,然后以某种方式作为请求参数传递。不,它只是在实际调用应用程序阶段执行的。

于 2013-09-17T00:38:30.357 回答