我在我的应用程序中添加了一个生命周期监听器,其灵感来自BalusC code的教程,并添加了时间戳来监控每个阶段需要多长时间。我期待“调用应用程序”阶段需要花费最长时间,但是日志让我意识到它需要大约827毫秒,而“渲染响应”阶段花了2890毫秒然后我想知道在这期间花了那么多时间“渲染响应”阶段。
据我快速了解the specification,在这个阶段唯一做的就是“渲染”(并且还保存响应的状态,但这里并不重要)所有应用程序应该先调用代码。它总是如此吗?
例如,如果我的页面包含默认值为#{myBean.valueAfterPost}的表单,那么在“调用应用程序”期间或“渲染响应”期间调用valueAfterPost的getter?
在渲染响应阶段,很容易消耗大量时间?
答案 0 :(得分:4)
如果要渲染的内容很复杂(需要大量评估),或者如果你的getter方法中有一些逻辑,那么很容易花费更多时间,你必须避免这种情况, t控制框架调用getter时。提醒JSF在此阶段基于您的模型构建整个视图。
在 INVOKE APPLICATION 中调用操作方法,只要在 RENDER RESPONSE 期间调用getter(或者如果应用程序设计得很好,则应该调用它们)。
为了提供启动示例,只需使用PhaseListener
:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head />
<h:body>
<h:form>
<ui:repeat var="str" value="#{bean.strings}">
#{str}
</ui:repeat>
<h:commandButton value="send" action="#{bean.action}" />
</h:form>
</h:body>
</html>
@ManagedBean
@ViewScoped
public class Bean implements Serializable {
List<String> strings = Arrays.asList("item1", "item2");
public List<String> getStrings() {
System.out.println("Get called");
return strings;
}
public void action() {
System.out.println("Strings " + strings + " sent");
}
}
这将首先点击此输出:
RESTORE_VIEW 1 started
RESTORE_VIEW 1 finished
RENDER_RESPONSE 6 started
Get called
Get called
RENDER_RESPONSE 6 finished
请注意,getter被调用了两次,实际上你无法控制调用getter的次数,这就是你不必在getter中做任何逻辑的原因。
稍后,如果提交表单,我们就有了这个输出:
RESTORE_VIEW 1 started
Get called
Get called
RESTORE_VIEW 1 finished
APPLY_REQUEST_VALUES 2 started
Get called
APPLY_REQUEST_VALUES 2 finished
PROCESS_VALIDATIONS 3 started
PROCESS_VALIDATIONS 3 finished
UPDATE_MODEL_VALUES 4 started
UPDATE_MODEL_VALUES 4 finished
INVOKE_APPLICATION 5 started
Strings [item1, item2] sent
INVOKE_APPLICATION 5 finished
RENDER_RESPONSE 6 started
Get called
Get called
RENDER_RESPONSE 6 finished
在这种情况下,getter方法在 RENDER RESPONSE 期间调用,但也在 RESTORE VIEW 和 APPLY REQUEST VALUES 中调用。 Jsf在 INVOKE APPLICATION 期间访问操作方法。