commandButton/commandLink/ajax 操作/侦听器方法未调用或输入值未设置/更新

2024-03-20

有时,在使用时<h:commandLink>, <h:commandButton> or <f:ajax>, the action, actionListener or listener与该标记关联的方法根本没有被调用。或者,bean 属性未随提交更新UIInput values.

出现这种情况的可能原因及解决方法有哪些?


介绍

每当UICommand成分 (<h:commandXxx>, <p:commandXxx>等)无法调用关联的操作方法,或者UIInput成分 (<h:inputXxx>, <p:inputXxxx>等)无法处理提交的值和/或更新模型值,并且您在服务器日志中没有看到任何可搜索的异常和/或警告,当您按照以下方式配置 ajax 异常处理程序时也没有看到JSF ajax 请求中的异常处理 https://stackoverflow.com/questions/27526753/exception-handling-in-jsf-ajax-requests,也不当您在中设置以下上下文参数时web.xml,

<context-param>
    <param-name>jakarta.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>

并且您在浏览器的 JavaScript 控制台中也没有看到任何可搜索到的错误和/或警告(在 Chrome/Firefox23+/IE9+ 中按 F12 打开 Web 开发人员工具集,然后打开Console选项卡),然后解决以下可能原因列表。

可能的原因

  1. UICommand and UIInput组件必须放置在一个UIForm组件,例如<h:form>(因此不是纯 HTML<form>),否则无法向服务器发送任何内容。UICommand组件也不得有type="button"属性,否则它将是一个死按钮,仅对 JavaScript 有用onclick。也可以看看如何发送表单输入值并调用 JSF bean 中的方法 https://stackoverflow.com/questions/3681123/how-to-get-hinputtext-values-from-gui-xhtml-into-java-class-jsf-bean and 不启动回发 https://stackoverflow.com/questions/12958208/hcommandbutton-does-not-initiate-a-postback.

  2. 不能嵌套多个UIForm彼此之间的组成部分。这在 HTML 中是非法的。浏览器行为未指定。小心包含文件!您可以使用UIForm组件并行,但它们在提交期间不会相互处理。您还应该注意“God Form”反模式;确保您不会无意中以相同的形式处理/验证所有其他(不可见)输入(例如,有一个隐藏的对话框,其中包含相同形式的所需输入)。也可以看看如何在JSF页面中使用?单一形式?多种形式?嵌套表格? https://stackoverflow.com/questions/7371903/using-multiple-hform-in-a-jsf-page.

  3. No UIInput应该发生值验证/转换错误。您可以使用<h:messages>显示任何特定输入未显示的任何消息<h:message>成分。不要忘记包括id of <h:messages> in the <f:ajax render>,如果有的话,这样它也会根据 ajax 请求进行更新。也可以看看按下 p:commandButton 时 h:messages 不显示消息 https://stackoverflow.com/questions/16175178/hmessages-does-not-display-messages-when-pcommandbutton-is-pressed.

  4. If UICommand or UIInput组件放置在迭代组件内,例如<h:dataTable>, <ui:repeat>等等,那么你需要确保完全相同value迭代组件的值在表单提交请求的应用请求值阶段被保留。 JSF 将重复它以查找单击的链接/按钮和提交的输入值。将 bean 放入视图范围和/或确保将数据模型加载到@PostConstructbean 的(因此不在 getter 方法中!)应该修复它。也可以看看我应该如何以及何时从 JSF dataTable 的数据库加载模型 https://stackoverflow.com/questions/5765853/when-should-i-load-the-collection-from-database-for-hdatatable.

  5. If UICommand or UIInput组件包含在动态源中,例如<ui:include src="#{bean.include}">,那么你需要保证完全相同#{bean.include}在表单提交请求的视图构建期间保留值。 JSF 将在构建组件树期间重新执行它。将 bean 放入视图范围和/或确保将数据模型加载到@PostConstructbean 的(因此不在 getter 方法中!)应该修复它。也可以看看如何通过导航菜单ajax刷新动态包含内容? (JSF SPA) https://stackoverflow.com/questions/7108668/how-to-ajax-refresh-dynamic-include-content-by-navigation-menu-jsf-spa.

  6. The rendered组件及其所有父组件的属性以及test任何父母的属性<c:if>/<c:when>不应评估为false在表单提交请求的应用请求值阶段。 JSF 将重新检查它,作为防止请求被篡改/黑客攻击的一部分。将负责条件的变量存储在@ViewScopedbean 或确保您正确地预初始化了条件@PostConstruct of a @RequestScopedbean 应该修复它。这同样适用于disabled and readonly组件的属性,不应评估为true在应用请求值阶段。也可以看看未调用 JSF CommandButton 操作 https://stackoverflow.com/questions/13326404/jsf-commandbutton-action-not-invoked, 不处理条件渲染组件中的表单提交 https://stackoverflow.com/questions/18782503/form-submit-in-conditionally-rendered-component-is-not-processed, 一旦我将 h:commandButton 包装在 中,它就无法工作 https://stackoverflow.com/questions/23742141/hcommandbutton-is-not-working-once-i-wrap-it-in-a-hpanelgroup-rendered and 无论如何强制 JSF 处理、验证和更新只读/禁用的输入组件 https://stackoverflow.com/questions/32390081/force-jsf-to-process-validate-and-update-readonly-disabled-input-components-any

  7. The onclick的属性UICommand组件和onsubmit的属性UIForm组件不应返回false或导致 JavaScript 错误。应该存在以下情况<h:commandLink> or <f:ajax>在浏览器的 JS 控制台中也看不到 JS 错误。通常谷歌搜索确切的错误消息已经给你答案了。也可以看看使用 PrimeFaces 手动添加/加载 jQuery 会导致未捕获的类型错误 https://stackoverflow.com/questions/16166039/adding-jquery-to-primefaces-results-in-uncaught-typeerror-over-all-place.

  8. 如果您通过 JSF 2.x 使用 Ajax<f:ajax>或例如PrimeFaces<p:commandXxx>,确保您有一个<h:head>在主模板中而不是<head>。否则,JSF 将无法自动包含包含 Ajax 函数的必要 JavaScript 文件。这将导致浏览器的 JS 控制台中出现 JavaScript 错误,例如“mojarra 未定义”或“PrimeFaces 未定义”。也可以看看与 f:ajax 和 ui:repeat 一起使用时,不会调用 h:commandLink actionlistener https://stackoverflow.com/questions/9933777/hcommandlink-actionlistener-is-not-invoked-when-used-with-fajax-and-uirepeat.

  9. 如果您使用 Ajax,并且提交的值最终为null,然后确保UIInput and UICommand感兴趣的组成部分涵盖在<f:ajax execute>或例如<p:commandXxx process>,否则它们将不会被执行/处理。也可以看看将 添加到 时,提交的表单值未在模型中更新 https://stackoverflow.com/questions/17960929/submitted-form-values-not-updated-in-model-when-adding-fajax-to-hcommandbut and 了解 PrimeFaces 进程/更新和 JSF f:ajax 执行/渲染属性 https://stackoverflow.com/questions/25339056/understanding-process-and-update-attributes-of-primefaces.

  10. 如果提交的值最终仍然是null,并且您正在使用 CDI 来管理 bean,然后确保从正确的包导入作用域注释,否则 CDI 将默认为@Dependent它在 EL 表达式的每次计算中有效地重新创建 bean。也可以看看@SessionScoped bean 失去作用域并一直被重新创建,字段变为 null https://stackoverflow.com/questions/9470440/sessionscoped-bean-looses-scope-and-gets-recreated-all-the-time-fields-become and JSF 2 应用程序中默认的托管 Bean 范围是什么? https://stackoverflow.com/questions/19322364/what-is-the-default-managed-bean-scope-in-a-jsf-2-application

  11. 如果父母的<h:form>UICommand按钮预先由来自同一页面中另一个表单的 ajax 请求呈现/更新,那么第一个操作在 JSF 2.2 或更早版本中将始终失败。第二个及后续操作将起作用。这是由视图状态处理中的错误引起的,报告为JSF 规范问题 790 https://github.com/jakartaee/faces/issues/790目前已在 JSF 2.3 中修复。对于较旧的 JSF 版本,您需要显式指定<h:form> in the render of the <f:ajax>。也可以看看h:commandButton/h:commandLink 在第一次单击时不起作用,仅在第二次单击时起作用 https://stackoverflow.com/questions/11408130/hcommandbutton-hcommandlink-does-not-work-on-first-click-works-only-on-second.

  12. If the <h:form> has enctype="multipart/form-data"设置以支持文件上传,那么您需要确保您使用的至少是 JSF 2.2,或者负责解析 multipart/form-data 请求的 servlet 过滤器已正确配置,否则FacesServlet最终将根本得不到请求参数,因此无法应用请求值。如何配置这样的过滤器取决于所使用的文件上传组件。对于战斧<t:inputFileUpload>, check 这个答案 https://stackoverflow.com/questions/5418292/jsf-2-0-file-upload/5424229#5424229对于 PrimeFaces<p:fileUpload>, check 这个答案 https://stackoverflow.com/questions/8875818/how-to-use-primefaces-pfileupload-listener-method-is-never-invoked/8880083#8880083。或者,如果您实际上根本没有上传文件,则完全删除该属性。

  13. 确保ActionEvent的论证actionListener is an jakarta.faces.event.ActionEvent因此不java.awt.event.ActionEvent,这是大多数 IDE 建议的第一个自动完成选项。如果您使用,没有参数也是错误的actionListener="#{bean.method}"。如果您不想在方法中使用参数,请使用actionListener="#{bean.method()}"。或者也许你真的想使用action代替actionListener。也可以看看动作和动作监听器之间的区别 https://stackoverflow.com/questions/3909267/differences-between-action-and-actionlistener.

  14. 确保没有PhaseListener or any EventListener请求-响应链中的 JSF 生命周期已更改为跳过调用操作阶段,例如通过调用FacesContext#renderResponse() or FacesContext#responseComplete().

  15. 确保没有Filter or Servlet在同一个请求-响应链中已经阻塞了FacesServlet不知何故。例如,登录/安全过滤器,例如 Spring Security。特别是在 ajax 请求中,默认情况下根本不会有任何 UI 反馈。也可以看看Spring Security 4 和 PrimeFaces 5 AJAX 请求处理 https://stackoverflow.com/questions/30133329/spring-security-4-and-primefaces-5-ajax-request-handling.

  16. 如果您使用的是 PrimeFaces<p:dialog> or a <p:overlayPanel>,然后确保他们有自己的<h:form>。因为,这些组件默认由 JavaScript 重新定位到 HTML 末尾<body>。所以,如果他们最初坐在一个<form>,那么他们现在就不再坐在<form>。也可以看看p:commandbutton 操作在 p:dialog 中不起作用 https://stackoverflow.com/questions/18958729/pcommandbutton-action-doesnt-work-inside-pdialog

调试提示

如果您仍然卡住,那么就该进行调试了。在客户端,在 Web 浏览器中按 F12 打开 Web 开发人员工具集。点击Console选项卡,以便查看 JavaScript 控制台。它应该没有任何 JavaScript 错误。下面的屏幕截图是来自 Chrome 的示例,演示了提交<f:ajax>启用按钮,但没有<h:head>声明(如上面第 7 点所述)。

点击Network选项卡可查看 HTTP 流量监视器。提交表单并调查请求标头、表单数据以及响应正文是否符合预期。下面的屏幕截图是来自 Chrome 的示例,它演示了一个简单表单的成功 ajax 提交,其中包含一个<h:inputText>和一个单一的<h:commandButton> with <f:ajax execute="@form" render="@form">.

(警告:当您从生产环境发布 HTTP 请求标头的屏幕截图(如上面所示)时,请确保对屏幕截图中的任何会话 cookie 进行加扰/混淆,以避免会话劫持攻击!)

在服务器端,确保服务器以调试模式启动。在您希望在处理表单提交期间调用的感兴趣的 JSF 组件的方法中放置一个调试断点。例如。的情况下UICommand组件,那就是UICommand#queueEvent() https://github.com/eclipse-ee4j/mojarra/blob/4.0.4-RELEASE/impl/src/main/java/jakarta/faces/component/UICommand.java#L222并且如果UIInput组件,那就是UIInput#validate() https://github.com/eclipse-ee4j/mojarra/blob/4.0.4-RELEASE/impl/src/main/java/jakarta/faces/component/UIInput.java#L782。只需逐步执行代码并检查流程和变量是否符合预期。下面的屏幕截图是 Eclipse 调试器的示例。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

commandButton/commandLink/ajax 操作/侦听器方法未调用或输入值未设置/更新 的相关文章

随机推荐