当 JSF 2 的视图中存在元数据转换器时,为啥 JSTL-JSF2 不能正常工作
Posted
技术标签:
【中文标题】当 JSF 2 的视图中存在元数据转换器时,为啥 JSTL-JSF2 不能正常工作【英文标题】:Why JSTL-JSF2 not work fine when exists metadata converter in the view in JSF 2当 JSF 2 的视图中存在元数据转换器时,为什么 JSTL-JSF2 不能正常工作 【发布时间】:2012-06-01 06:04:01 【问题描述】:仅当在 JSF 视图中我删除 JSTL 代码时,按钮才会调用操作方法,我知道这是生命周期,但我不明白原因/问题。我喜欢妥协,因为它会引发这种行为。
查看代码工作正常
<f:metadata>
<f:viewParam name="idAsociacion" value="#msgUsuario.asociacion" converter="#
asociacionConverter"
converterMessage="#msg['aplicacion.asociacion.error.converter']" required="true"
requiredMessage="#msg['aplicacion.asociacion.error.required']" />
<f:viewParam name="idMsg" value="#msgUsuario.mensajeRespondido" converter="#
mensajeConverter" converterMessage="#msg['aplicacion.mensaje.error.converter']"
required="true" requiredMessage="#msg['aplicacion.mensaje.error.required']" />
</f:metadata>
<ui:decorate template="/WEB-INF/templates/mainUsuario-template.xhtml">
<ui:define name="title">
<h:outputFormat value="#msg['usuario.escribirMsj.title']">
<f:param value="#msgUsuario.asociacion.nombre" />
</h:outputFormat>
</ui:define>
<ui:param name="descripcionView" value="#msg['usuario.escribirMsj.descripcion']" />
<ui:define name="content">
<h:panelGroup layout="block"
id="escribirMensajeContainer"styleClass="escribirMensajeContainer">
<h:form>
<p:panelGrid>
<p:row>
<p:column>
<h:outputLabel for="texto" value="#msg['usuario.escribirMsj.mensaje']"
styleClass="labelInput" />
</p:column>
</p:row>
<p:row>
<p:column>
<p:inputTextarea autoResize="true" cols="80" rows="15" id="texto"
maxlength="500" value="#msgUsuario.texto">
</p:inputTextarea>
</p:column>
</p:row>
<p:row>
<p:column>
<h:message for="texto" id="messageMensajeError" styleClass="messageError" />
</p:column>
</p:row>
<p:row>
<p:column>
<p:commandButton action="#msgUsuario.enviar"
tabindex="2" title="#
fn:replace(msg['usuario.escribirMsj.title.enviar'],0,msgUsuario.asociacion.nombre)"
value="#msg['usuario.escribirMsj.enviar']" />
</p:column>
</p:row>
</p:panelGrid>
</h:form>
</h:panelGroup>
</ui:define>
</ui:decorate>
</html>
但是,如果我添加 JSTL,我将在下面显示。视图渲染良好,因为消息没有得到响应,但按钮从不调用操作方法并且视图重新加载。
<c:choose>
<c:when test="#msgUsuario.mensajeRespondido.respondido==false">
<h:form>
<p:panelGrid>
<p:row>
<p:column>
<h:outputLabel for="texto" value="#msg['usuario.escribirMsj.mensaje']"
styleClass="labelInput" />
</p:column>
</p:row>
<p:row>
<p:column>
<p:inputTextarea autoResize="true" cols="80" rows="15" id="texto"
maxlength="500" value="#msgUsuario.texto">
</p:inputTextarea>
</p:column>
</p:row>
<p:row>
<p:column>
<h:message for="texto" id="messageMensajeError" styleClass="messageError" />
</p:column>
</p:row>
<p:row>
<p:column>
<p:commandButton action="#msgUsuario.enviar"
tabindex="2" title="#
fn:replace(msg['usuario.escribirMsj.title.enviar'],0,msgUsuario.asociacion.nombre)"
value="#msg['usuario.escribirMsj.enviar']" />
</p:column>
</p:row>
</p:panelGrid>
</h:form>
</c:when>
<c:otherwise>
<h:outputText value="MESSAGE RESPONSED" />
</c:otherwise>
</c:choose>
注意:转换在两种情况下都可以正常工作。
ManagedBean 代码
@ManagedBean(name="msgUsuario")
@ViewScoped
public class EscribirMensajeUsuarioView implements Serializable
private static final long serialVersionUID = 1L;
private static final Logger logger=Logger.getLogger(EscribirMensajeUsuarioView.class);
private Asociacion asociacion;
private Mensaje mensajeRespondido;
private Usuario usuario;
private String texto;
private boolean usuarioBloqueado;
@ManagedProperty(value="#mensajeBO")
private MensajeBO mensajeBo;
@ManagedProperty(value="#usuarioBO")
private UsuarioBO usuarioBo;
/* Never invoked with JSTL code in the view */
public String enviar()
logger.info("EscribirMensajesUsuarioView.enviar");
TipoMensaje tipoMensaje=null;
Mensaje mensaje=this.mensajeRespondido;
.................
.................
.................
/* Getters and Setters */
我读了这个 Balusc 的评论
“JSF 和 JSTL 不会像您对编码所期望的那样同步运行。JSTL 在视图的构建期间运行(当要填充 JSF 组件树时),而 JSF 在视图的渲染期间运行组件树(当要生成 HTML 输出时)。您可以将其可视化为:JSTL 先从上到下运行,然后将结果交给 JSF,JSF 再从上到下运行。”
例如,我在 dinamyc 数据表中理解这一点,但在这种情况下不是。因为 JSTL 可以很好地呈现 mensajeRepetido 在 JSF 树中退出的视图,但按钮不会调用该方法。但是视图重新加载并且 mensajeRepetido 由转换器再次退出。 p>
亲切的问候。
【问题讨论】:
【参考方案1】:您的问题是由于您将 JSTL 属性绑定到 view scoped 托管 bean 属性而引起的。这仅在关闭部分状态保存时才有效。打开部分状态保存(默认情况下)后,JSTL 属性将获得其自己的 second 视图范围 bean 实例(所有属性都设置为默认值!),而不是存储在 JSF 视图中的实例状态并被 JSF 组件使用。
只需使用JSF组件的rendered
属性而不是通常的方式,并且使用JSTL只控制视图的构建,而不是控制视图的呈现。
<h:form rendered="#not msgUsuario.mensajeRespondido.respondido">
...
<h:form>
<h:panelGroup rendered="#msgUsuario.mensajeRespondido.respondido">
<h:outputText value="MESSAGE RESPONSED" />
</h:panelGroup>
另见:
JSTL in JSF2 Facelets... makes sense? Communication in JSF 2.0 -@ViewScoped
fails in taghandlers
【讨论】:
感谢您的回复。我不明白“仅使用 JSTL 来控制视图的构建,而不是控制视图的呈现”。有什么区别? 视图的构建是将 XHTML 文件转换为 JSF 组件树的步骤,context.getViewRoot()
提供。视图的呈现是通过调用viewRoot.encodeAll(context)
将JSF 组件树转换为HTML 输出的步骤。 JSTL 在构建视图期间运行,并且不存在于 JSF 组件树中。该视图建立在每个 GET 请求之上,并在每个后续 POST 请求中重用,该请求通过隐藏输入字段 javax.faces.ViewState
标识视图。
在 JSF 2.2 中,视图范围是在构建视图之前恢复的,因此 JSTL 和其他构建时标记可以访问视图范围 bean(如果这是一件好事是另一个问题)。
我有更清晰的概念。我阅读了问题 1492,我认为这是一个很好的通知,虽然使用渲染属性解决了这个任务,但最好让 JSTL 更接近。非常感谢……以上是关于当 JSF 2 的视图中存在元数据转换器时,为啥 JSTL-JSF2 不能正常工作的主要内容,如果未能解决你的问题,请参考以下文章
为啥 UIComponent.setStyleClass() 在 JSF 2.1 转换器中不起作用?
为啥当我将 hbm2ddl.auto 设置为创建时,Hibernate 会抛出 SQLGrammarException 说表/视图不存在?