我正在使用JSF 2.2 + Primefaces开发WebApp ...项目正在快速增长,并且第一次性能测试非常差(由于我对JSF LifeCylce在非功能性需求方面的了解不足 - 即完全ajax网站),然后我们可以改善一点,但结果仍然,不如预期。 (根据动作,我们有300~1500毫秒的时间,想法是性能大约500毫秒,给予或采取)。主要是还原视图阶段和渲染响应是消费者(在其他情况下花费的时间毫无价值)的时间。对于某些操作,调用应用程序也需要时间(由于DB调用)。
在网上阅读了很多文章之后,有很多很棒的提示需要考虑(很多当然来自stackoverflow),例如:
- 改善数据库查询
我们有一些复杂的,用两个Hibernate Criterias查询完成,所以我们在这里工作。 (也许使用纯SQL查询,复杂的查询使用子查询?)
- 永远不要在Bean的getters上定义业务逻辑
知道了!
- 将适当的范围设置为bean并在其上存储只不过是必要的东西
我们有一个完整的ajax站点,因此View Scoped几乎就像Session Scoped一样,我们使用SessionBeans作为一种' Cache'存储我们不希望每次都从DB获取的关键数据+在此处定义业务逻辑。
- 选择正确的JSF状态保存方法 - 客户端服务器
为此我需要进行更多的研究,检查各种可能性的优缺点,然后测试每一种的可能性。
到目前为止非常清楚,现在有些额外的提示,我有些疑惑。
- 尽可能使用vanilla HTML,最好使用h:tags而不是p:tags
简单的HTML是清楚的,有意义的,现在在h:和p之间:它值多少钱?例如。
<p:commandButton value="Value"
styleClass="class"
actionListener="#{myBean.doStuff()}"
ajax="true" process="@form" update="@form"
onsuccess="jsFunction()" />
VS
<h:commandButton value="Value"
styleClass="class"
actionListener="#{myBean.doStuff()}" >
<f:ajax execute="@form" render="@form" event="onclick" />
</h:commandButton>
或
<ui:fragment... vs <p:fragment...
或
<p:outputLabel value="#{myBean.value}" rendered="#{myBean.shouldRender}" />
VS
<ui:fragment rendered="#{myBean.shouldRender}">
<label>#{myBean.value}</label>
</ui:fragment>
我一直在混合使用Primefaces和Jsf标签以及一些简单的HTML现在。(主要是由于它们的组件的功能)我现在认为纯HTML总是如此更快,但在JSF和另一个框架之间?如果我这样做,改变它将花费大量时间,我不会喜欢知道它根本没有产生相关差异的结果。
- 自定义Facelets标记与复合组件
我认为这是关键。对于它们的差异仍有一些疑问,对于它们的实现, CC 使用起来非常简单和灵活,但缺点是它们完全包含在ViewTree和JSF为每个请求重新生成(如果我没有弄错的话,虽然自定义标签使用起来似乎有点复杂(不是那么多),但其优点是只有ViewTree中包含的内容才会被包含在内更多,使RESTORE VIEW更省时。我们有几个复合组件,没有Facelets标签,所以这里要做很多工作。我仍然没有找到一篇很好的文章来解释它们之间的差异,当一个应该被使用时,另一个(已经读过输入,消息使用TAGS和更复杂的东西CC)。如果想要更喜欢标签与CC,那么我将没有选择而不是使用CC?在CC中使用自定义标签是否可以使它们更轻松地用于处理它们?
我即将进入修改洞穴项目的旅程,以获得更好的表现,这将花费我几天的时间,想法是这次获得更好的结果;所以每个提示,建议和建议都非常欢迎!谢谢你的时间!
答案 0 :(得分:1)
半年前我遇到了同样的问题。大多数时间花在 RestoreView 和 RenderResponse 阶段。如果你的问题是一样的话 你无能为力:
partialSubmit="true"
在我的特定情况下,我有很多没有输入控件的动态HTML 我使用复合组件作为条件渲染的模板。 为了提高性能,我使用freemarker生成动态html。
PS。如果我们有包含许多组件的复杂页面,我的意见是不使用JSF。我认为Tapestry对此更为优化。它不像JSF那样在每个请求上重新创建组件。
答案 1 :(得分:1)
您可以采取一些措施来提高屏幕效果
要查看您的内容是否已经使用gzip和缓存,请执行 Google Chrome 浏览器 - &gt;右键点击你的屏幕 - &gt;检查 - &gt;点击网络标签 - &gt;刷新你的屏幕。 点击图片,图标,样式表,看看您是否在响应标题
中看到了以下内容 Cache-Control:max-age=2592000
如果元素的状态是304(来自缓存)
Content-Encoding:gzip
如果元素的状态为200
答案 2 :(得分:1)
RenderResponse需要98%的时间,因为......这就是JSF主要做的事情。如果JSF将请求的处理时间的50%用于执行除了呈现响应之外的其他事情,我会担心!你需要深入挖掘。考虑这个例子。
假设您有一个显示表格的页面。您可以使用p:dataTable PrimeFaces组件,如下所示:
<h:html>
<h:body>
<p:dataTable value="#{myBean.data}">
</p:dataTable>
</h:body>
</h:html>
你有@ManagedBean
:
@ManagedBean(name="myBean")
public class MyBean {
public List<MyObject> getData() {
return // fetch list from database;
}
}
每次调用getData()
时,都会有数据库访问权限,并且该时间会增加呈现阶段的全局时间。而且,p:dataTable的渲染可能需要多次调用getData。
同样,您需要深入了解应用程序,并在呈现阶段确切地检测到花费的时间。根据我的经验,@ManagedBean
的朴素实现在xhtml
中引用的相同getter中有很多数据库查询代码,就像我之前的例子一样。 JSF(或像PrimeFaces的p:dataTable这样的组件)可能会在渲染单个xhtml时多次调用这些getter。常见的策略是使用preRenderView事件仅获取一次数据,如下所示:
在你的xhtml中:
<h:html>
<f:metadata>
<f:event type="preRenderView" listener="#{myBean.fetchDAta}"/>
</f:metadata>
<h:body>
<p:dataTable value="#{myBean.data}">
</p:dataTable>
</h:body>
</h:html>
在托管bean中:
@ManagedBean(name="myBean")
public class MyBean {
private List<MyObject> data;
public void fetchData() {
data = // fetch data from database.
}
public List<MyObject> getData() {
return data;
}
}
答案 3 :(得分:-1)
我不确定“p”和“h”之间是否存在很大差异,因为它们都会在结尾处呈现为html。我看到你使用了很多进程属性。您可以通过仅发送表单的某些部分来定位此属性中的特定ID以提高性能。提高性能的另一个想法是使用primefaces“cache”。 http://www.primefaces.org/showcase/ui/misc/cache.xhtml表示您希望非常频繁地呈现的非动态内容(请查看文档)。我猜“缓存”会尝试从缓存中获取树视图而不是重建它。
答案 4 :(得分:-2)
我读了一篇关于JSF加速性能的有趣文章。在恢复视图阶段,JSF重构组件树,包括将数据绑定到数据表,从而导致从数据库中不必要地提取数据。本文着眼于避免额外工作来获取数据的一种方法。
我在这里报告可能的解决方案,以及完整的文章供参考。
该问题的解决方案是首次跳过获取数据。它不是必需的,甚至没有使用它甚至不是正确的数据(不用担心,我稍后会解释)。在FacesContext对象中有一个名为getRenderResponse()的方法,如果已经调用了渲染响应方法并且我们处于渲染阶段,则该方法返回true。在我们渲染页面之前,我们并不真正需要我们的数据,因此只有在此方法返回true时才加载它。
例如:
//generates the list of data, think of this as an expensive DB operation
private List<Integer> generateData() {
if (!FacesContext.getCurrentInstance().getRenderResponse()) {
return null;
}
System.out.println("Generating Data starting from "+pageNumber);
...
...
...
}
因此,即使在回发中我们也只能获得每页请求一次数据获取,因为我们不需要在渲染响应中真正需要加载数据,如果您查看时间,我们的页面加载速度是原来的两倍我们只获取了一半的数据。
所以你去,你可以通过只在你真正需要的时候加载数据来提高你的JSF页面的速度,我想这是一种懒惰的加载数据。
Double the speed of (some of) your JSF pages (and dodge bugs too)
我希望它对其他人有用。
答案 5 :(得分:-2)
如果你想用其他框架制作jsf应用程序你的应用程序对用户来说性能很差。因为Jsf应用程序变成了等待渲染阶段太多的6阶段。因此,您可以将微服务用于后端,并使用javascript作为前端。结果您可以在性能和体系结构方面做出如此好的应用。你可以看看java ee应用程序的spring boot微服务