【发布时间】:2018-03-21 13:47:52
【问题描述】:
今天我花了几个小时在我们的 Web 应用程序中使用 JSF facelets 重现了一个非常奇怪的 UI 行为: 在某些情况下,在服务器端真正完成呈现整个视图之前,UI 已在 Web 浏览器中部分呈现。
最后,这一切都归结为一个包含大量元素的 JSF 视图——在我的例子中是一个子菜单项。似乎有一些阈值会触发响应的部分刷新。
这是一个最小化的示例,直观地展示了这种效果:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="de" xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<style>
td {
vertical-align: top;
}
</style>
</h:head>
<h:body>
<h1>EURNEU-10056</h1>
<table>
<tr>
<td>
<ol>
<ui:repeat value="#{bean.strings(10)}" var="str">
<li><h:outputText value="#{str}" /></li>
</ui:repeat>
</ol>
<h:outputText value="#{bean.delay(2000)}" />
</td>
<td>
<ol>
<ui:repeat value="#{bean.strings(10)}" var="str">
<li><h:outputText value="#{str}" /></li>
</ui:repeat>
</ol>
<h:outputText value="#{bean.delay(2000)}" />
</td>
<td><ol>
<ui:repeat value="#{bean.strings(10)}" var="str">
<li><h:outputText value="#{str}" /></li>
</ui:repeat>
</ol>
<h:outputText value="#{bean.delay(2000)}" />
</td>
</tr>
</table>
</h:body>
</html>
该简单视图使用以下 bean 生成一定数量的字符串,并在 3 列中的每一列之后的 2000ms 渲染中添加一些 人为延迟。 p>
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.faces.bean.ManagedBean;
@ManagedBean
public class Bean implements Serializable {
private static final long serialVersionUID = 1L;
public List<String> strings(int count) {
List<String> all = new ArrayList<>();
for (int i = 0; i < count; i++) {
all.add(UUID.randomUUID().toString());
}
return all;
}
public String delay(int delay) {
try {
Thread.sleep(delay);
}
catch (InterruptedException ex) {
// NOP;
}
return String.format("This string has been delayed for %d ms!", delay);
}
}
浏览器在处理请求时显示以下阶段:
如果我在生成视图时减少使用的字符串数量,则响应只会在渲染阶段结束时刷新。
我可以做些什么来避免部分渲染?(除了减少元素的数量)
PS:我们使用 JBoss EAP v7.0.9 作为服务器。应用程序本身相当复杂。
【问题讨论】:
-
这不是什么奇怪的行为。那是缓冲输出。如果您有一个输出信息行的 3 小时运行流程,您希望在流程结束之前获取这些行。如果您的输出为 17MB 或 100MB,该怎么办。谁必须缓冲它才能不做部分输出?
-
我们用 32kB 的 HTML 代码实现了刷新效果……它与 JSF 视图中的元素数量有关……而不是 HTML 的输出大小。
-
但原则仍然存在。也许,JSF 控件会执行一些刷新或强制刷新。
-
当然...但是我可以调整任何设置吗? BufferSize 某处?我仍在寻找导致该效果的相关组件/设置。否则我必须在我们的 UI 中改造菜单。在大多数情况下效果很小……但有些页面需要大约 10 秒才能完成完整渲染阶段,用户看到部分加载的页面会感到很困惑。
-
10 秒!!!那不是对话速度……在 glassfish 'server-config' - 'HTTP Service' 中,您会找到 32k 缓冲区。或“服务器配置”-“网络配置”-“协议”-“http-listener1”-“HTTP”