JSF Converter似乎是在xhtml页面上的任何其他托管bean之前调用的.它甚至可以rendered=false在h:selectOneMenu组件上创建.
我已经创建了3个托管bean来测试初始化序列,并且托管bean按顺序初始化它们出现在xhtml中,但在它们之前,尽管是最后一个创建了JSF转换器.
形成
<h:form>
<h:inputText value="#{creationTime1.string1}"/>
<h:inputText value="#{creationTime3.string3}"/>
<h:inputText value="#{creationTime2.string2}"/>
<h:selectOneMenu value="#{creationTime1.competitor}" rendered="false" converter="#{testConverter}" >
<f:selectItem itemValue="#{null}" itemLabel="#{msg.none}" />
<f:selectItems value="#{creationTime1.competitorList}" var="competitor" itemValue="#{competitor}"
itemLabel="#{competitor.idCompetitor}"/>
</h:selectOneMenu>
<h:commandButton value="GO" action="#{creationTime1.submit}"/>
</h:form>
Run Code Online (Sandbox Code Playgroud)
变流器
@Named(value = "testConverter")
@ViewScoped
public class TestConverter implements Converter, Serializable {
@PostConstruct
private void init() {
System.out.println(System.currentTimeMillis() + " || TestConverter init");
}
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
...
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
管理豆(所有相同的名称)
@Named(value = "creationTime2")
@ViewScoped
public class CreationTime2 implements Serializable {
private String string2;
public String getString2() {
System.out.println("getter srting2");
return string2;
}
public void setString2(String string2) {
this.string2 = string2;
}
@PostConstruct
private void init() {
System.out.println(System.currentTimeMillis() + " || CreationTime2 init");
}
}
Run Code Online (Sandbox Code Playgroud)
页面访问结果
Info: START PHASE RESTORE_VIEW 1
Info: END PHASE RESTORE_VIEW 1
Info: START PHASE RENDER_RESPONSE 6
Info: 1451147920374 || TestConverter init
Info: 1451147920401 || CreationTime1 init
Info: getter string1
Info: 1451147920407 || CreationTime3 init
Info: getter string3
Info: 1451147920414 || CreationTime2 init
Info: getter string2
Info: END PHASE RENDER_RESPONSE 6
Run Code Online (Sandbox Code Playgroud)
我也尝试用@FacesConverter而不是CDI bean,结果是一样的.
rendered=false?h:celectOneMenu它不应该只是通过不存在而不创造自己吗?运用
为什么在任何其他bean之前调用转换器?
这里没有完全"调用"转换器,即在那一刻既不调用getAsObject()也不getAsString()调用.它只是在构建视图时实例化,然后被指定为父ValueHolder组件的属性.JSF为组件上声明的每个转换器,验证器和(ajax)行为执行此操作.
转换器实际上是一个托管bean在这方面没有区别.这只是一个技巧,以便能够在其中注入EJB.JSF检查值是文字字符串还是EL表达式.如果是文字字符串,则将其视为转换器ID以创建转换器实例,否则如果EL表达式返回具体Converter实例,则直接使用它.或者如果没有,那么JSF将通过匹配value类型的目标类创建转换器(如果有的话).
为什么转换器是用创建的
rendered=false?
因为该rendered属性仅在视图渲染时评估,而不是在视图构建时.
我可以以某种方式使转换器在这3个bean之后创建自己(按照它出现在xhtml页面上)吗?
不,但如果你担心转换器的"不必要"实例化,那么你可以使用JSTL有条件地添加转换器.
<h:selectOneMenu ... rendered="#{bean.condition}">
<c:if test="#{bean.condition}"><f:converter binding="#{testConverter}" /></c:if>
...
</h:selectOneMenu>
Run Code Online (Sandbox Code Playgroud)
您只需要记住,<x:someComponent rendered>并且<c:if test>不会在同一时间进行评估.将<c:if test>在视图生成时进行评估,在<x:someComponent rendered>视图中进行评估的渲染时间.因此,如果由于某种原因条件恰好在这些时刻之间发生变化,那么您基本上需要重建视图(即显式导航到同一视图而不是返回void/ null).如果在重新创建bean时条件绑定到视图范围的bean属性,这可能会变得很糟糕.你基本上需要在其中保留条件@PostConstruct.
尽管如此,无论如何要实例化的转换器(以及验证器和行为)应该是您最不关心的问题.如果在实例化方面遇到性能损失,或者在实例化排序方面存在技术问题,那么根据具体的功能要求,您最好寻找不同的解决方案.
| 归档时间: |
|
| 查看次数: |
304 次 |
| 最近记录: |