我很好奇 JSF 是如何知道我点击了按钮和一些 Action 的,甚至可以调用带有参数的 Action 监听器。我可以想象服务器注意到状态和 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>
最佳答案
在应用请求值阶段, decode()
所有的方法UIComponent
组件树中的实例被执行。这是检查和收集必要的 HTTP 请求参数的地方。如果是UIInput
组件(<h:inputText>
和 friend ),已获取提交的值。如果是UICommand
组件(<h:commandButton>
和 friend ),ActionEvent
已排队。
如果是<p:commandButton>
所有的魔法都发生在 CommandButtonRenderer#decode()
中谁是source code的相关部分提取如下(行号来自 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 HTML , 你应该已经知道 name=value
每个输入元素的一对,只有封闭表单的按下按钮作为请求参数发送到服务器。 PrimeFaces 命令按钮基本上生成以下 HTML,
<button type="submit" name="formId:buttonId" ... />
哪里formId:buttonId
打印自 UIComponent#getClientId()
.正是这个值被用作 HTTP 请求参数名称(HTTP 请求参数值是按钮的标签,但这里不再相关)。如果您熟悉 basic Servlets ,JSF 在其上运行,那么您应该已经知道请求参数可以通过 HttpServletRequest#getParameter()
获得。 ,包括 name=value
一对按钮。这允许 distinguishing the pressed button .
正如您在上面看到的 decode()
方法,正是这个 UIComponent#getClientId()
value 也用于检查 HTTP 请求参数映射是否包含参数名称。如果是这样,那么一个 ActionEvent
将排队,最终在调用应用程序阶段被调用。
至于 EL 论点,这实际上不是火箭科学。整个 EL 表达式仅在调用应用程序阶段执行。它不是在生成表单的 HTML 输出期间执行的,然后以某种方式作为请求参数传递的。不,它只是在实际调用应用程序阶段执行的。
关于jsf - JSF 如何处理 Action 监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18837049/