如何在 Struts 2 中访问 OGNL 跟踪评估?

问题描述 投票:0回答:2

我被告知要优化网络应用程序。为此,我使用 JProfiler

我注意到很大一部分响应时间花费在表示层。特别是当代码构建 HTML 代码时。

深入研究这个瓶颈,我发现代码涉及大量 OGNL 类/方法(接近 50% 的调用)。

我通过删除一些不必要的 OGNL 语句来调整 JSP 代码(详细信息见下文)。我设法获得了 200 毫秒。然而,代码在这个瓶颈上仍然平均花费超过 2000 毫秒。整体响应时间在3000ms左右。

OGNL 文档这样说:

从 OGNL 2.5.0 开始,OgnlContext 对象可以自动“跟踪表达式的评估”。 (...) 您可以通过 OgnlContext 的 lastEvaluation 属性访问最后一次评估。 由于我使用 Struts 2.3.15.1 (OGNL v3.0.6),如何从 JSP 文件或 Action 类访问此属性或调用

getLastEvaluation

OgnlContext


JSP 文件

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix ="s" uri="/struts-tags" %> <!DOCTYPE html> <html> <head> <title><s:text name="domain.domain0.title"/></title> <script type="text/javascript" src="<s:url value='/js/domain/domain0.js'/>"></script> <script type="text/javascript" src="<s:url value='/js/core/html.js'/>"></script> </head> <body> <div style="width:100%;color:green;font-weight: bold;text-align:center"> <s:text name="domain.domain0.information"/> </div> <div class="content selectFen"> <s:set var="noAnchor">false</s:set> <s:iterator value="artefactList" status="numRow"> <s:if test="court == nomenclatureCritere && #noAnchor!=true"> <s:set var="noAnchor">true</s:set> <a id="NomencAnchor" href="#NomencAnchor" style="visibility:hidden;"></a> </s:if> <s:set var="isOpen" value="nomenclatureCritere.startsWith(court) || ligProd != '80'"/> <div class="parcoursNomenc"> <table onmouseover='this.style.backgroundColor="gainsboro"' onmouseout='this.style.backgroundColor=""' style="width: 100%;font-weight:bolder"> <tbody> <tr> <s:url var="childNomenUrl" action="ajaxPopupNomenChild" escapeAmp="false"> <s:param name="dateCritere" value="dateCritere"/> <s:param name="sidNomenclaturePere" value="sidArtNomenc"/> </s:url> <s:if test="#isOpen"> <s:if test="#numRow.last"> <td onclick="noeudPlusMoins(this);loadChild('<s:property value="childNomenUrl" />', 'divParcours<s:property value="sidArtNomenc"/>')" class="open_last">&#160;</td> </s:if> <s:else> <td onclick="noeudPlusMoins(this);loadChild('<s:property value="childNomenUrl" />', 'divParcours<s:property value="sidArtNomenc"/>')" class="open">&#160;</td> </s:else> </s:if> <s:else> <s:if test="#numRow.last"> <td onclick="noeudPlusMoins(this);loadChild('<s:property value="childNomenUrl" />', 'divParcours<s:property value="sidArtNomenc"/>')" class="closed_last">&#160;</td> </s:if> <s:else> <td onclick="noeudPlusMoins(this);loadChild('<s:property value="childNomenUrl" />', 'divParcours<s:property value="sidArtNomenc"/>')" class="closed">&#160;</td> </s:else> </s:else> <td style="vertical-align: top; width: 8.5em; padding-top: 5px;"> <s:text name="domain.domain0.label"/> <s:property value="court"/> </td> <td class="description"> <s:property value="description"/> </td> </tr> </tbody> </table> <div id="divParcours<s:property value="sidArtNomenc"/>" class="<s:if test="numRow.last">subtree_last</s:if><s:else>subtree</s:else>" > <s:if test="#isOpen"> <s:action name="popupNomenExist" executeResult="true"> <s:param name="dateCritere" value="dateCritere"/> <s:param name="nomenclatureCritere" value="nomenclatureCritere"/> </s:action> <s:action name="ajaxPopupNomenChild" executeResult="true"> <s:param name="dateCritere" value="dateCritere"/> <s:param name="sidNomenclaturePere" value="sidArtNomenc"/> </s:action> </s:if> </div> </div> </s:iterator> </div> </body> </html>

查看您的 JSP 代码,很明显罪魁祸首是 
java jsp struts2 struts ognl
2个回答
1
投票
标签:

您在
each

迭代中调用两个操作...基于您正在迭代的行数,可能会成为一个严重的问题。

我会尝试重构该部分;瓶颈的很大一部分在于解释标签、调用操作、通过拦截器堆栈等的机制。

如果您可以生成相同的输出,最大限度地减少对操作的调用,那么瓶颈将显着减少。

P.S:一个非常小的优化是更改 s:if 中布尔值和字符串比较的顺序,以利用短路(布尔比较更快):

<s:if test="#noAnchor!=true && court == nomenclatureCritere">


编辑

没有

s:action
效果更好,但是页面需要它们,我不知道如何替换它们


更清楚地说,动作应该

执行一个(或几个)逻辑

动作
  • 永远不要用作辅助类。
  • 当你调用
  • popupNomenExist
时,你唯一的要求就是调用服务器,做一些事情,并接收结果并将其注入 JSP 中。

有多种方法可以接收该结果,调用 Action 可能是最差的(就性能而言,由于上面列出的原因)。

您可以从

execute()

操作的

popupNomenExist

 方法中获取代码,并且:
将其放入您当前操作的方法中,如 RomanC 链接答案中所述;

    将其放入辅助类的静态方法中;
  1. 在当前操作中预先计算它,并将结果公开为字符串列表;
  2. 等等...
  3. 此外,我们不能争论
  4. what
到底是在 popupNomenExist 的

execute() 方法中执行的,但我想它有可能被重构以防止执行每次迭代、分组时通用的某些逻辑部分它们并在迭代之前作为一种缓存执行。


您可以像

© www.soinside.com 2019 - 2024. All rights reserved.