JSF如何处理动作监听器?

时间:2013-09-16 20:48:15

标签: jsf jsf-2 actionlistener

我很好奇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>

1 个答案:

答案 0 :(得分:7)

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

如果<p:commandButton> CommandButtonRenderer#decode()发生了source code的所有魔法,basic HTML的相关部分在下面提取(行号来自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  }

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

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

formId:buttonId打印UIComponent#getClientId()。正是这个值被用作HTTP请求参数名称(HTTP请求参数值是按钮的标签,但这里没有进一步的相关性)。如果您熟悉JSF运行的distinguishing the pressed button,那么您应该已经知道HttpServletRequest#getParameter()可以使用请求参数,包括name=value对按钮。这允许{{3}}。

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

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