JSF页面Cancel按钮需点击两次才返回搜索页问题求助
你的问题核心是AJAX请求中执行重定向时,JSF的AJAX引擎未正确处理重定向响应,导致首次点击只有POST请求但后端方法未执行(或执行了但页面没跳转),第二次点击才生效。结合你的代码和场景,主要有几个可能的原因和对应解决方案:
原因1:AJAX请求与重定向的冲突
<p:commandButton ajax="true">发起的AJAX请求,JSF默认期望返回部分视图更新的响应,而非页面重定向。当你在后端执行redirect()时,浏览器收到重定向状态码,但AJAX引擎不会自动触发页面跳转;第二次点击时,视图状态或请求上下文变化,才触发跳转。
解决方案:关闭AJAX跳转
重定向是页面级跳转,不需要AJAX支持,直接将按钮的ajax设为false:
<p:commandButton value="Cancel" id="cancelToSearch" action="#{partQuoteSearchBackingBean.performCancel('SearchScreen')}" ajax="false" />
原因2:表单验证拦截请求
如果页面中其他组件存在required="true"或自定义验证规则,首次点击Cancel按钮时,JSF会先执行表单验证,若验证失败,后端的performCancel方法不会被调用(因此无日志输出)。第二次点击可能因视图状态变化或验证条件满足,才触发方法执行。
解决方案:跳过验证
给Cancel按钮添加immediate="true",让请求在JSF生命周期的应用请求值阶段就处理,跳过后续的验证和模型更新:
<p:commandButton value="Cancel" id="cancelToSearch" action="#{partQuoteSearchBackingBean.performCancel('SearchScreen')}" ajax="true" immediate="true" />
原因3:AJAX重定向未正确终止响应
即使后端执行了redirect(),若未明确终止JSF响应,可能导致AJAX引擎继续等待视图更新,无法处理重定向。
解决方案:在后端方法中添加响应终止
修改performCancel方法,在redirect()后调用responseComplete():
public void performCancel(String targetPage){ logger.debug("targetPage: " + targetPage); logger.info("targetPage: " + targetPage); try{ if("SearchScreen".equals(targetPage)){ FacesContext.getCurrentInstance().getExternalContext().redirect("partQuoteSearch.xhtml"); }else if("Home".equals(targetPage)){ FacesContext.getCurrentInstance().getExternalContext().redirect("index.xhtml"); } else if("enterPartQuote".equals(targetPage)){ setFieldFocus("enterPartQuoteFormId:formFocusID","enterPartQuoteFormId:partNumber"); FacesContext.getCurrentInstance().getExternalContext().redirect("enterPartQuote.xhtml"); } // 添加这行,终止JSF响应 FacesContext.getCurrentInstance().responseComplete(); } catch (Exception e) { handleSystemException(e, "messages"); } }
备选方案:AJAX成功后前端跳转
如果必须保留AJAX,可以通过按钮的oncomplete事件,在请求成功后直接前端跳转,无需后端重定向:
<p:commandButton value="Cancel" id="cancelToSearch" action="#{partQuoteSearchBackingBean.performCancel('SearchScreen')}" ajax="true" oncomplete="window.location.href='partQuoteSearch.xhtml'" />
此时后端方法可以去掉redirect(),仅处理必要的业务逻辑即可。
内容的提问来源于stack exchange,提问作者SK.

