PrimeFaces 5.3.15 DefaultCommand资源404问题排查
Spring 3.1.4 + JSF 2.2 + PrimeFaces 5.3.15 开发环境下,表单业务功能运行正常,但浏览器开发者工具Network面板检测到2项PrimeFaces资源请求返回404错误:
defaultcommand.css.xhtml?ln=primefaces&v=5.3.15defaultcommand.js.xhtml?ln=primefaces&v=5.3.15
对应表单代码如下:
<h:form styleClass="smsForm"> <h:panelGroup layout="block" styleClass="separarArribaMas separarAbajoMas"> <p:commandButton global="false" action="#{proposicionBean.botonIrPedirTelefono()}" onclick="PF('estadoOperacionDialog').show();" oncomplete="PF('estadoOperacionDialog').hide();" title="#{msg['sms.citainternet.cita.botonConfirmarCita.mensaje']}" styleClass="accion colorPrimario" value="#{msg['sms.citainternet.cita.botonSiguientePasoCita']}" ajax="false"/> <p:commandButton global="false" action="#{proposicionBean.botonIrCambiarCitaMobile()}" onclick="PF('estadoOperacionDialog').show();" oncomplete="PF('estadoOperacionDialog').hide();" title="#{msg['sms.citainternet.cita.botonCambiarCita.mensaje']}" styleClass="accion" value="#{msg['sms.citainternet.cita.botonCambiarCita']}" ajax="false"/> <p:commandButton ajax="true" onclick="mostrarDialogo();" title="#{msg['mensaje.volver.pagina.inicio']}" styleClass="accion rojo" global="false" value="#{msg['sms.citainternet.botonCancelar']}"/> </h:panelGroup> <h:panelGroup layout="block" styleClass="separarArribaMas"> <p class="ayuda"> <h:outputFormat value="#{msg['sms.citainternet.cita.citaPropuesta.texto.ayuda']}" escape="false"> <f:param value="#{msg['sms.citainternet.cita.botonSiguientePasoCita']}"/> </h:outputFormat> </p> </h:panelGroup> <h:outputScript> function mostrarDialogo() { PF('dialogoDeseaVolver').show(); $('body').addClass("ocultar"); $("#wrapper").attr("aria-hidden", "true"); $("#dialogoDeseaVolverFoco").focus(); } </h:outputScript> </h:form>
PrimeFaces 5.3版本存在默认逻辑:当<h:form>标签内部存在配置了ajax="false"的<p:commandButton>非异步提交按钮时,框架会自动为该表单注入DefaultCommand组件的依赖资源(对应css和js文件),用来实现「表单内按下回车键自动触发第一个提交按钮」的默认行为,不需要开发者显式编写<p:defaultCommand>标签。
上述表单代码中前两个<p:commandButton>都配置了ajax="false",正是触发资源自动加载的直接原因。
资源返回404的核心原因一般是两类配置冲突:要么Faces Servlet的后缀映射和PrimeFaces生成资源路径的规则不匹配,要么Spring的DispatcherServlet拦截了JSF静态资源路径/javax.faces.resource/*且没有做放行配置。由于当前表单没有依赖DefaultCommand的回车提交逻辑,所以资源加载失败不会影响现有业务功能运行。
根据实际需求选以下任意一种方案即可:
方案1:全局关闭DefaultCommand自动注入
如果项目不需要表单默认回车触发提交的能力,直接在web.xml中添加PrimeFaces上下文参数,关闭自动注入逻辑,配置后只有显式编写<p:defaultCommand>标签时才会加载对应资源:
<context-param> <param-name>primefaces.DEFAULT_COMMAND_AUTO</param-name> <param-value>false</param-value> </context-param>
方案2:替换非异步提交按钮为原生JSF按钮
如果不想修改全局配置,可以将表单中所有ajax="false"的<p:commandButton>替换为原生<h:commandButton>,手动追加PrimeFaces按钮的基础样式类保持视觉效果一致即可。替换后PrimeFaces不会识别到表单内存在非异步提交的p按钮,就不会自动注入DefaultCommand资源。
以第一个按钮为例,替换后代码如下:
<h:commandButton action="#{proposicionBean.botonIrPedirTelefono()}" onclick="PF('estadoOperacionDialog').show();" oncomplete="PF('estadoOperacionDialog').hide();" title="#{msg['sms.citainternet.cita.botonConfirmarCita.mensaje']}" styleClass="accion colorPrimario ui-button ui-widget ui-state-default ui-corner-all" value="#{msg['sms.citainternet.cita.botonSiguientePasoCita']}"/>
方案3:需要默认回车功能时修复404而非屏蔽加载
如果业务上需要表单回车默认提交的能力,不需要屏蔽资源加载,只需修复配置解决404即可:
- 确认
web.xml中Faces Servlet的映射规则为*.xhtml,不要自定义其他后缀,避免PrimeFaces生成的资源路径后缀匹配失败 - 在Spring MVC配置中放行JSF静态资源路径,不要让DispatcherServlet拦截
/javax.faces.resource/**的请求,示例配置:
<mvc:resources mapping="/javax.faces.resource/**" location="classpath:/META-INF/resources/"/>
内容的提问来源于stack exchange,提问作者Red1

