我很好奇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>
答案 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输出时执行,然后以某种方式作为请求参数传递。不,它刚刚在实际调用应用程序阶段执行。